ADD: new track message, Entity class and Position class
This commit is contained in:
165
libs/eigen/test/AnnoyingScalar.h
Normal file
165
libs/eigen/test/AnnoyingScalar.h
Normal file
@@ -0,0 +1,165 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011-2018 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/.
|
||||
|
||||
#ifndef EIGEN_TEST_ANNOYING_SCALAR_H
|
||||
#define EIGEN_TEST_ANNOYING_SCALAR_H
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#if EIGEN_COMP_GNUC
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#endif
|
||||
|
||||
#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
|
||||
struct my_exception
|
||||
{
|
||||
my_exception() {}
|
||||
~my_exception() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
// An AnnoyingScalar is a pseudo scalar type that:
|
||||
// - can randomly through an exception in operator +
|
||||
// - randomly allocate on the heap or initialize a reference to itself making it non trivially copyable, nor movable, nor relocatable.
|
||||
|
||||
class AnnoyingScalar
|
||||
{
|
||||
public:
|
||||
AnnoyingScalar() { init(); *v = 0; }
|
||||
AnnoyingScalar(long double _v) { init(); *v = _v; }
|
||||
AnnoyingScalar(double _v) { init(); *v = _v; }
|
||||
AnnoyingScalar(float _v) { init(); *v = _v; }
|
||||
AnnoyingScalar(int _v) { init(); *v = _v; }
|
||||
AnnoyingScalar(long _v) { init(); *v = _v; }
|
||||
#if EIGEN_HAS_CXX11
|
||||
AnnoyingScalar(long long _v) { init(); *v = _v; }
|
||||
#endif
|
||||
AnnoyingScalar(const AnnoyingScalar& other) { init(); *v = *(other.v); }
|
||||
~AnnoyingScalar() {
|
||||
if(v!=&data)
|
||||
delete v;
|
||||
instances--;
|
||||
}
|
||||
|
||||
void init() {
|
||||
if(internal::random<bool>())
|
||||
v = new float;
|
||||
else
|
||||
v = &data;
|
||||
instances++;
|
||||
}
|
||||
|
||||
AnnoyingScalar operator+(const AnnoyingScalar& other) const
|
||||
{
|
||||
#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
|
||||
countdown--;
|
||||
if(countdown<=0 && !dont_throw)
|
||||
throw my_exception();
|
||||
#endif
|
||||
return AnnoyingScalar(*v+*other.v);
|
||||
}
|
||||
|
||||
AnnoyingScalar operator-() const
|
||||
{ return AnnoyingScalar(-*v); }
|
||||
|
||||
AnnoyingScalar operator-(const AnnoyingScalar& other) const
|
||||
{ return AnnoyingScalar(*v-*other.v); }
|
||||
|
||||
AnnoyingScalar operator*(const AnnoyingScalar& other) const
|
||||
{ return AnnoyingScalar((*v)*(*other.v)); }
|
||||
|
||||
AnnoyingScalar operator/(const AnnoyingScalar& other) const
|
||||
{ return AnnoyingScalar((*v)/(*other.v)); }
|
||||
|
||||
AnnoyingScalar& operator+=(const AnnoyingScalar& other) { *v += *other.v; return *this; }
|
||||
AnnoyingScalar& operator-=(const AnnoyingScalar& other) { *v -= *other.v; return *this; }
|
||||
AnnoyingScalar& operator*=(const AnnoyingScalar& other) { *v *= *other.v; return *this; }
|
||||
AnnoyingScalar& operator/=(const AnnoyingScalar& other) { *v /= *other.v; return *this; }
|
||||
AnnoyingScalar& operator= (const AnnoyingScalar& other) { *v = *other.v; return *this; }
|
||||
|
||||
bool operator==(const AnnoyingScalar& other) const { return *v == *other.v; }
|
||||
bool operator!=(const AnnoyingScalar& other) const { return *v != *other.v; }
|
||||
bool operator<=(const AnnoyingScalar& other) const { return *v <= *other.v; }
|
||||
bool operator< (const AnnoyingScalar& other) const { return *v < *other.v; }
|
||||
bool operator>=(const AnnoyingScalar& other) const { return *v >= *other.v; }
|
||||
bool operator> (const AnnoyingScalar& other) const { return *v > *other.v; }
|
||||
|
||||
float* v;
|
||||
float data;
|
||||
static int instances;
|
||||
#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
|
||||
static int countdown;
|
||||
static bool dont_throw;
|
||||
#endif
|
||||
};
|
||||
|
||||
AnnoyingScalar real(const AnnoyingScalar &x) { return x; }
|
||||
AnnoyingScalar imag(const AnnoyingScalar & ) { return 0; }
|
||||
AnnoyingScalar conj(const AnnoyingScalar &x) { return x; }
|
||||
AnnoyingScalar sqrt(const AnnoyingScalar &x) { return std::sqrt(*x.v); }
|
||||
AnnoyingScalar abs (const AnnoyingScalar &x) { return std::abs(*x.v); }
|
||||
AnnoyingScalar cos (const AnnoyingScalar &x) { return std::cos(*x.v); }
|
||||
AnnoyingScalar sin (const AnnoyingScalar &x) { return std::sin(*x.v); }
|
||||
AnnoyingScalar acos(const AnnoyingScalar &x) { return std::acos(*x.v); }
|
||||
AnnoyingScalar atan2(const AnnoyingScalar &y,const AnnoyingScalar &x) { return std::atan2(*y.v,*x.v); }
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream,const AnnoyingScalar& x) {
|
||||
stream << (*(x.v));
|
||||
return stream;
|
||||
}
|
||||
|
||||
int AnnoyingScalar::instances = 0;
|
||||
|
||||
#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
|
||||
int AnnoyingScalar::countdown = 0;
|
||||
bool AnnoyingScalar::dont_throw = false;
|
||||
#endif
|
||||
|
||||
namespace Eigen {
|
||||
template<>
|
||||
struct NumTraits<AnnoyingScalar> : NumTraits<float>
|
||||
{
|
||||
enum {
|
||||
RequireInitialization = 1,
|
||||
};
|
||||
typedef AnnoyingScalar Real;
|
||||
typedef AnnoyingScalar Nested;
|
||||
typedef AnnoyingScalar Literal;
|
||||
typedef AnnoyingScalar NonInteger;
|
||||
};
|
||||
|
||||
template<> inline AnnoyingScalar test_precision<AnnoyingScalar>() { return test_precision<float>(); }
|
||||
|
||||
namespace numext {
|
||||
template<>
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
|
||||
bool (isfinite)(const AnnoyingScalar& x) {
|
||||
return (numext::isfinite)(*x.v);
|
||||
}
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
template<> EIGEN_STRONG_INLINE double cast(const AnnoyingScalar& x) { return double(*x.v); }
|
||||
template<> EIGEN_STRONG_INLINE float cast(const AnnoyingScalar& x) { return *x.v; }
|
||||
}
|
||||
} // namespace Eigen
|
||||
|
||||
AnnoyingScalar get_test_precision(const AnnoyingScalar&)
|
||||
{ return Eigen::test_precision<AnnoyingScalar>(); }
|
||||
|
||||
AnnoyingScalar test_relative_error(const AnnoyingScalar &a, const AnnoyingScalar &b)
|
||||
{ return test_relative_error(*a.v, *b.v); }
|
||||
|
||||
inline bool test_isApprox(const AnnoyingScalar &a, const AnnoyingScalar &b)
|
||||
{ return internal::isApprox(*a.v, *b.v, test_precision<float>()); }
|
||||
|
||||
inline bool test_isMuchSmallerThan(const AnnoyingScalar &a, const AnnoyingScalar &b)
|
||||
{ return test_isMuchSmallerThan(*a.v, *b.v); }
|
||||
|
||||
#endif // EIGEN_TEST_ANNOYING_SCALAR_H
|
||||
465
libs/eigen/test/CMakeLists.txt
Normal file
465
libs/eigen/test/CMakeLists.txt
Normal file
@@ -0,0 +1,465 @@
|
||||
# The file split_test_helper.h was generated at first run,
|
||||
# it is now included in test/
|
||||
if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h)
|
||||
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h)
|
||||
endif()
|
||||
|
||||
# check if we have a Fortran compiler
|
||||
include(CheckLanguage)
|
||||
check_language(Fortran)
|
||||
if(CMAKE_Fortran_COMPILER)
|
||||
enable_language(Fortran)
|
||||
set(EIGEN_Fortran_COMPILER_WORKS ON)
|
||||
else()
|
||||
set(EIGEN_Fortran_COMPILER_WORKS OFF)
|
||||
# search for a default Lapack library to complete Eigen's one
|
||||
find_package(LAPACK QUIET)
|
||||
endif()
|
||||
|
||||
# TODO do the same for EXTERNAL_LAPACK
|
||||
option(EIGEN_TEST_EXTERNAL_BLAS "Use external BLAS library for testsuite" OFF)
|
||||
if(EIGEN_TEST_EXTERNAL_BLAS)
|
||||
find_package(BLAS REQUIRED)
|
||||
message(STATUS "BLAS_COMPILER_FLAGS: ${BLAS_COMPILER_FLAGS}")
|
||||
add_definitions("-DEIGEN_USE_BLAS") # is adding ${BLAS_COMPILER_FLAGS} necessary?
|
||||
list(APPEND EXTERNAL_LIBS "${BLAS_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# configure blas/lapack (use Eigen's ones)
|
||||
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)
|
||||
if(NOT WIN32)
|
||||
message(STATUS "Test realworld sparse matrices: ${EIGEN_TEST_MATRIX_DIR}")
|
||||
add_definitions( -DTEST_REAL_CASES="${EIGEN_TEST_MATRIX_DIR}" )
|
||||
else()
|
||||
message(STATUS "REAL CASES CAN NOT BE CURRENTLY TESTED ON WIN32")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SPARSE_LIBS " ")
|
||||
|
||||
find_package(CHOLMOD)
|
||||
if(CHOLMOD_FOUND)
|
||||
add_definitions("-DEIGEN_CHOLMOD_SUPPORT")
|
||||
include_directories(${CHOLMOD_INCLUDES})
|
||||
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)
|
||||
add_definitions("-DEIGEN_UMFPACK_SUPPORT")
|
||||
include_directories(${UMFPACK_INCLUDES})
|
||||
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(KLU)
|
||||
if(KLU_FOUND)
|
||||
add_definitions("-DEIGEN_KLU_SUPPORT")
|
||||
include_directories(${KLU_INCLUDES})
|
||||
set(SPARSE_LIBS ${SPARSE_LIBS} ${KLU_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
|
||||
set(KLU_ALL_LIBS ${KLU_LIBRARIES} ${EIGEN_BLAS_LIBRARIES})
|
||||
ei_add_property(EIGEN_TESTED_BACKENDS "KLU, ")
|
||||
else()
|
||||
ei_add_property(EIGEN_MISSING_BACKENDS "KLU, ")
|
||||
endif()
|
||||
|
||||
find_package(SuperLU 4.0)
|
||||
if(SuperLU_FOUND)
|
||||
add_definitions("-DEIGEN_SUPERLU_SUPPORT")
|
||||
include_directories(${SUPERLU_INCLUDES})
|
||||
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, ")
|
||||
endif()
|
||||
|
||||
|
||||
find_package(PASTIX QUIET COMPONENTS METIS SEQ)
|
||||
# check that the PASTIX found is a version without MPI
|
||||
find_path(PASTIX_pastix_nompi.h_INCLUDE_DIRS
|
||||
NAMES pastix_nompi.h
|
||||
HINTS ${PASTIX_INCLUDE_DIRS}
|
||||
)
|
||||
if (NOT PASTIX_pastix_nompi.h_INCLUDE_DIRS)
|
||||
message(STATUS "A version of Pastix has been found but pastix_nompi.h does not exist in the include directory."
|
||||
" Because Eigen tests require a version without MPI, we disable the Pastix backend.")
|
||||
endif()
|
||||
if(PASTIX_FOUND AND PASTIX_pastix_nompi.h_INCLUDE_DIRS)
|
||||
add_definitions("-DEIGEN_PASTIX_SUPPORT")
|
||||
include_directories(${PASTIX_INCLUDE_DIRS_DEP})
|
||||
if(SCOTCH_FOUND)
|
||||
include_directories(${SCOTCH_INCLUDE_DIRS})
|
||||
set(PASTIX_LIBRARIES ${PASTIX_LIBRARIES} ${SCOTCH_LIBRARIES})
|
||||
elseif(METIS_FOUND)
|
||||
include_directories(${METIS_INCLUDE_DIRS})
|
||||
set(PASTIX_LIBRARIES ${PASTIX_LIBRARIES} ${METIS_LIBRARIES})
|
||||
else()
|
||||
ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ")
|
||||
endif()
|
||||
set(SPARSE_LIBS ${SPARSE_LIBS} ${PASTIX_LIBRARIES_DEP} ${ORDERING_LIBRARIES})
|
||||
set(PASTIX_ALL_LIBS ${PASTIX_LIBRARIES_DEP})
|
||||
ei_add_property(EIGEN_TESTED_BACKENDS "PaStiX, ")
|
||||
else()
|
||||
ei_add_property(EIGEN_MISSING_BACKENDS "PaStiX, ")
|
||||
endif()
|
||||
|
||||
if(METIS_FOUND)
|
||||
add_definitions("-DEIGEN_METIS_SUPPORT")
|
||||
include_directories(${METIS_INCLUDE_DIRS})
|
||||
ei_add_property(EIGEN_TESTED_BACKENDS "METIS, ")
|
||||
else()
|
||||
ei_add_property(EIGEN_MISSING_BACKENDS "METIS, ")
|
||||
endif()
|
||||
|
||||
find_package(SPQR)
|
||||
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)
|
||||
if(NOT EIGEN_TEST_NOQT)
|
||||
find_package(Qt4)
|
||||
if(QT4_FOUND)
|
||||
include(${QT_USE_FILE})
|
||||
ei_add_property(EIGEN_TESTED_BACKENDS "Qt4 support, ")
|
||||
else()
|
||||
ei_add_property(EIGEN_MISSING_BACKENDS "Qt4 support, ")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(TEST_LIB)
|
||||
add_definitions("-DEIGEN_EXTERN_INSTANTIATIONS=1")
|
||||
endif()
|
||||
|
||||
set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Official")
|
||||
add_custom_target(BuildOfficial)
|
||||
|
||||
ei_add_test(rand)
|
||||
ei_add_test(meta)
|
||||
ei_add_test(numext)
|
||||
ei_add_test(sizeof)
|
||||
ei_add_test(dynalloc)
|
||||
ei_add_test(nomalloc)
|
||||
ei_add_test(first_aligned)
|
||||
ei_add_test(type_alias)
|
||||
ei_add_test(nullary)
|
||||
ei_add_test(mixingtypes)
|
||||
ei_add_test(io)
|
||||
ei_add_test(packetmath "-DEIGEN_FAST_MATH=1")
|
||||
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(unalignedcount)
|
||||
if(NOT EIGEN_TEST_NO_EXCEPTIONS AND NOT EIGEN_TEST_OPENMP)
|
||||
ei_add_test(exceptions)
|
||||
endif()
|
||||
ei_add_test(redux)
|
||||
ei_add_test(visitor)
|
||||
ei_add_test(block)
|
||||
ei_add_test(corners)
|
||||
ei_add_test(symbolic_index)
|
||||
ei_add_test(indexed_view)
|
||||
ei_add_test(reshape)
|
||||
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)
|
||||
ei_add_test(diagonalmatrices)
|
||||
ei_add_test(adjoint)
|
||||
ei_add_test(diagonal)
|
||||
ei_add_test(miscmatrices)
|
||||
ei_add_test(commainitializer)
|
||||
ei_add_test(smallvectors)
|
||||
ei_add_test(mapped_matrix)
|
||||
ei_add_test(mapstride)
|
||||
ei_add_test(mapstaticmethods)
|
||||
ei_add_test(array_cwise)
|
||||
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)
|
||||
ei_add_test(product_symm)
|
||||
ei_add_test(product_syrk)
|
||||
ei_add_test(product_trmv)
|
||||
ei_add_test(product_trmm)
|
||||
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)
|
||||
ei_add_test(determinant)
|
||||
ei_add_test(inverse)
|
||||
ei_add_test(qr)
|
||||
ei_add_test(qr_colpivoting)
|
||||
ei_add_test(qr_fullpivoting)
|
||||
ei_add_test(upperbidiagonalization)
|
||||
ei_add_test(hessenberg)
|
||||
ei_add_test(schur_real)
|
||||
ei_add_test(schur_complex)
|
||||
ei_add_test(eigensolver_selfadjoint)
|
||||
ei_add_test(eigensolver_generic)
|
||||
ei_add_test(eigensolver_complex)
|
||||
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_quaternion)
|
||||
ei_add_test(geo_eulerangles)
|
||||
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(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(sparse_permutations)
|
||||
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(nestbyvalue)
|
||||
ei_add_test(zerosized)
|
||||
ei_add_test(dontalign)
|
||||
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(bfloat16_float)
|
||||
ei_add_test(array_of_string)
|
||||
ei_add_test(num_dimensions)
|
||||
ei_add_test(stl_iterators)
|
||||
ei_add_test(blasutil)
|
||||
if(EIGEN_TEST_CXX11)
|
||||
ei_add_test(initializer_list_construction)
|
||||
ei_add_test(diagonal_matrix_variadic_ctor)
|
||||
endif()
|
||||
|
||||
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(fastmath " ${EIGEN_FASTMATH_FLAGS} ")
|
||||
|
||||
# # ei_add_test(denseLM)
|
||||
|
||||
if(QT4_FOUND)
|
||||
ei_add_test(qtvector "" "${QT_QTCORE_LIBRARY}")
|
||||
endif()
|
||||
|
||||
if(UMFPACK_FOUND)
|
||||
ei_add_test(umfpack_support "" "${UMFPACK_ALL_LIBS}")
|
||||
endif()
|
||||
|
||||
if(KLU_FOUND OR SuiteSparse_FOUND)
|
||||
ei_add_test(klu_support "" "${KLU_ALL_LIBS}")
|
||||
endif()
|
||||
|
||||
if(SUPERLU_FOUND)
|
||||
ei_add_test(superlu_support "" "${SUPERLU_ALL_LIBS}")
|
||||
endif()
|
||||
|
||||
if(CHOLMOD_FOUND)
|
||||
ei_add_test(cholmod_support "" "${CHOLMOD_ALL_LIBS}")
|
||||
endif()
|
||||
|
||||
if(PARDISO_FOUND)
|
||||
ei_add_test(pardiso_support "" "${PARDISO_ALL_LIBS}")
|
||||
endif()
|
||||
|
||||
if(PASTIX_FOUND AND (SCOTCH_FOUND OR METIS_FOUND))
|
||||
ei_add_test(pastix_support "" "${PASTIX_ALL_LIBS}")
|
||||
endif()
|
||||
|
||||
if(SPQR_FOUND AND CHOLMOD_FOUND)
|
||||
ei_add_test(spqr_support "" "${SPQR_ALL_LIBS}")
|
||||
endif()
|
||||
|
||||
if(METIS_FOUND)
|
||||
ei_add_test(metis_support "" "${METIS_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
string(TOLOWER "${CMAKE_CXX_COMPILER}" cmake_cxx_compiler_tolower)
|
||||
if(cmake_cxx_compiler_tolower MATCHES "qcc")
|
||||
set(CXX_IS_QCC "ON")
|
||||
endif()
|
||||
|
||||
ei_add_property(EIGEN_TESTING_SUMMARY "CXX: ${CMAKE_CXX_COMPILER}\n")
|
||||
if(CMAKE_COMPILER_IS_GNUCXX AND NOT CXX_IS_QCC)
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version COMMAND head -n 1 OUTPUT_VARIABLE EIGEN_CXX_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
ei_add_property(EIGEN_TESTING_SUMMARY "CXX_VERSION: ${EIGEN_CXX_VERSION_STRING}\n")
|
||||
endif()
|
||||
ei_add_property(EIGEN_TESTING_SUMMARY "CXX_FLAGS: ${CMAKE_CXX_FLAGS}\n")
|
||||
if (EIGEN_TEST_CUSTOM_CXX_FLAGS)
|
||||
ei_add_property(EIGEN_TESTING_SUMMARY "Custom CXX flags: ${EIGEN_TEST_CUSTOM_CXX_FLAGS}\n")
|
||||
endif()
|
||||
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)
|
||||
message(WARNING "The Eigen2 test suite has been removed")
|
||||
endif()
|
||||
|
||||
# boost MP unit test
|
||||
find_package(Boost 1.53.0)
|
||||
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)
|
||||
|
||||
set(EIGEN_CUDA_RELAXED_CONSTEXPR "--expt-relaxed-constexpr")
|
||||
if (${CUDA_VERSION} STREQUAL "7.0")
|
||||
set(EIGEN_CUDA_RELAXED_CONSTEXPR "--relaxed-constexpr")
|
||||
endif()
|
||||
|
||||
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")
|
||||
string(APPEND CMAKE_CXX_FLAGS " --cuda-path=${CUDA_TOOLKIT_ROOT_DIR}")
|
||||
foreach(GPU IN LISTS EIGEN_CUDA_COMPUTE_ARCH)
|
||||
string(APPEND CMAKE_CXX_FLAGS " --cuda-gpu-arch=sm_${GPU}")
|
||||
endforeach()
|
||||
else()
|
||||
foreach(GPU IN LISTS EIGEN_CUDA_COMPUTE_ARCH)
|
||||
string(APPEND CUDA_NVCC_FLAGS " -gencode arch=compute_${GPU},code=sm_${GPU}")
|
||||
endforeach()
|
||||
endif()
|
||||
string(APPEND CUDA_NVCC_FLAGS " ${EIGEN_CUDA_RELAXED_CONSTEXPR}")
|
||||
set(EIGEN_ADD_TEST_FILENAME_EXTENSION "cu")
|
||||
|
||||
ei_add_test(gpu_basic)
|
||||
|
||||
unset(EIGEN_ADD_TEST_FILENAME_EXTENSION)
|
||||
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
# HIP unit tests
|
||||
option(EIGEN_TEST_HIP "Add HIP support." OFF)
|
||||
if (EIGEN_TEST_HIP)
|
||||
|
||||
set(HIP_PATH "/opt/rocm/hip" CACHE STRING "Path to the HIP installation.")
|
||||
|
||||
if (EXISTS ${HIP_PATH})
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${HIP_PATH}/cmake)
|
||||
|
||||
find_package(HIP REQUIRED)
|
||||
if (HIP_FOUND)
|
||||
|
||||
execute_process(COMMAND ${HIP_PATH}/bin/hipconfig --platform OUTPUT_VARIABLE HIP_PLATFORM)
|
||||
|
||||
if ((${HIP_PLATFORM} STREQUAL "hcc") OR (${HIP_PLATFORM} STREQUAL "amd"))
|
||||
|
||||
include_directories(${HIP_PATH}/include)
|
||||
|
||||
set(EIGEN_ADD_TEST_FILENAME_EXTENSION "cu")
|
||||
ei_add_test(gpu_basic)
|
||||
unset(EIGEN_ADD_TEST_FILENAME_EXTENSION)
|
||||
|
||||
elseif ((${HIP_PLATFORM} STREQUAL "nvcc") OR (${HIP_PLATFORM} STREQUAL "nvidia"))
|
||||
message(FATAL_ERROR "HIP_PLATFORM = nvcc is not supported within Eigen")
|
||||
else ()
|
||||
message(FATAL_ERROR "Unknown HIP_PLATFORM = ${HIP_PLATFORM}")
|
||||
endif()
|
||||
endif()
|
||||
else ()
|
||||
message(FATAL_ERROR "EIGEN_TEST_HIP is ON, but the specified HIP_PATH (${HIP_PATH}) does not exist")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cmake_dependent_option(EIGEN_TEST_BUILD_DOCUMENTATION "Test building the doxygen documentation" OFF "EIGEN_BUILD_DOC" OFF)
|
||||
if(EIGEN_TEST_BUILD_DOCUMENTATION)
|
||||
add_dependencies(buildtests doc)
|
||||
endif()
|
||||
|
||||
# Register all smoke tests
|
||||
include("EigenSmokeTestList")
|
||||
ei_add_smoke_tests("${ei_smoke_test_list}")
|
||||
35
libs/eigen/test/MovableScalar.h
Normal file
35
libs/eigen/test/MovableScalar.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2020 Sebastien Boisvert <seb@boisvert.info>
|
||||
//
|
||||
// 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_MISC_MOVABLE_SCALAR_H
|
||||
#define EIGEN_MISC_MOVABLE_SCALAR_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Eigen
|
||||
{
|
||||
template <typename Scalar, typename Base = std::vector<Scalar>>
|
||||
struct MovableScalar : public Base
|
||||
{
|
||||
MovableScalar() = default;
|
||||
~MovableScalar() = default;
|
||||
MovableScalar(const MovableScalar&) = default;
|
||||
MovableScalar(MovableScalar&& other) = default;
|
||||
MovableScalar& operator=(const MovableScalar&) = default;
|
||||
MovableScalar& operator=(MovableScalar&& other) = default;
|
||||
MovableScalar(Scalar scalar) : Base(100, scalar) {}
|
||||
|
||||
operator Scalar() const { return this->size() > 0 ? this->back() : Scalar(); }
|
||||
};
|
||||
|
||||
template<> struct NumTraits<MovableScalar<float>> : GenericNumTraits<float> {};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
30
libs/eigen/test/SafeScalar.h
Normal file
30
libs/eigen/test/SafeScalar.h
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
// A Scalar that asserts for uninitialized access.
|
||||
template<typename T>
|
||||
class SafeScalar {
|
||||
public:
|
||||
SafeScalar() : initialized_(false) {}
|
||||
SafeScalar(const SafeScalar& other) {
|
||||
*this = other;
|
||||
}
|
||||
SafeScalar& operator=(const SafeScalar& other) {
|
||||
val_ = T(other);
|
||||
initialized_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SafeScalar(T val) : val_(val), initialized_(true) {}
|
||||
SafeScalar& operator=(T val) {
|
||||
val_ = val;
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
VERIFY(initialized_ && "Uninitialized access.");
|
||||
return val_;
|
||||
}
|
||||
|
||||
private:
|
||||
T val_;
|
||||
bool initialized_;
|
||||
};
|
||||
219
libs/eigen/test/adjoint.cpp
Normal file
219
libs/eigen/test/adjoint.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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 "main.h"
|
||||
|
||||
template<bool IsInteger> struct adjoint_specific;
|
||||
|
||||
template<> struct adjoint_specific<true> {
|
||||
template<typename Vec, typename Mat, typename Scalar>
|
||||
static void run(const Vec& v1, const Vec& v2, Vec& v3, const Mat& square, Scalar s1, Scalar s2) {
|
||||
VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3), numext::conj(s1) * v1.dot(v3) + numext::conj(s2) * v2.dot(v3), 0));
|
||||
VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2), s1*v3.dot(v1)+s2*v3.dot(v2), 0));
|
||||
|
||||
// check compatibility of dot and adjoint
|
||||
VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), 0));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct adjoint_specific<false> {
|
||||
template<typename Vec, typename Mat, typename Scalar>
|
||||
static void run(const Vec& v1, const Vec& v2, Vec& v3, const Mat& square, Scalar s1, Scalar s2) {
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
using std::abs;
|
||||
|
||||
RealScalar ref = NumTraits<Scalar>::IsInteger ? RealScalar(0) : (std::max)((s1 * v1 + s2 * v2).norm(),v3.norm());
|
||||
VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3), numext::conj(s1) * v1.dot(v3) + numext::conj(s2) * v2.dot(v3), ref));
|
||||
VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2), s1*v3.dot(v1)+s2*v3.dot(v2), ref));
|
||||
|
||||
VERIFY_IS_APPROX(v1.squaredNorm(), v1.norm() * v1.norm());
|
||||
// check normalized() and normalize()
|
||||
VERIFY_IS_APPROX(v1, v1.norm() * v1.normalized());
|
||||
v3 = v1;
|
||||
v3.normalize();
|
||||
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()));
|
||||
VERIFY(internal::isMuchSmallerThan(abs(v1.dot(square * v2) - (square.adjoint() * v1).dot(v2)), ref, test_precision<Scalar>()));
|
||||
|
||||
// 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(Vec::Random(v1.size()).normalized().norm(), RealScalar(1));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename MatrixType> void adjoint(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Transpose.h Conjugate.h Dot.h
|
||||
*/
|
||||
using std::abs;
|
||||
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;
|
||||
const Index PacketSize = internal::packet_traits<Scalar>::size;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
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 = internal::random<Scalar>(),
|
||||
s2 = internal::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(), numext::conj(s1) * m1.adjoint());
|
||||
|
||||
// check basic properties of dot, squaredNorm
|
||||
VERIFY_IS_APPROX(numext::conj(v1.dot(v2)), v2.dot(v1));
|
||||
VERIFY_IS_APPROX(numext::real(v1.dot(v1)), v1.squaredNorm());
|
||||
|
||||
adjoint_specific<NumTraits<Scalar>::IsInteger>::run(v1, v2, v3, square, s1, s2);
|
||||
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(abs(vzero.dot(v1)), static_cast<RealScalar>(1));
|
||||
|
||||
// like in testBasicStuff, test operator() to check const-qualification
|
||||
Index r = internal::random<Index>(0, rows-1),
|
||||
c = internal::random<Index>(0, cols-1);
|
||||
VERIFY_IS_APPROX(m1.conjugate()(r,c), numext::conj(m1(r,c)));
|
||||
VERIFY_IS_APPROX(m1.adjoint()(c,r), numext::conj(m1(r,c)));
|
||||
|
||||
// check inplace transpose
|
||||
m3 = m1;
|
||||
m3.transposeInPlace();
|
||||
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;
|
||||
m3.adjointInPlace();
|
||||
VERIFY_IS_APPROX(m3,m1.adjoint());
|
||||
m3.transposeInPlace();
|
||||
VERIFY_IS_APPROX(m3,m1.conjugate());
|
||||
|
||||
// check mixed dot product
|
||||
typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
|
||||
RealVectorType rv1 = RealVectorType::Random(rows);
|
||||
VERIFY_IS_APPROX(v1.dot(rv1.template cast<Scalar>()), v1.dot(rv1));
|
||||
VERIFY_IS_APPROX(rv1.template cast<Scalar>().dot(v1), rv1.dot(v1));
|
||||
|
||||
VERIFY( is_same_type(m1,m1.template conjugateIf<false>()) );
|
||||
VERIFY( is_same_type(m1.conjugate(),m1.template conjugateIf<true>()) );
|
||||
}
|
||||
|
||||
template<int>
|
||||
void adjoint_extra()
|
||||
{
|
||||
MatrixXcf a(10,10), b(10,10);
|
||||
VERIFY_RAISES_ASSERT(a = a.transpose());
|
||||
VERIFY_RAISES_ASSERT(a = a.transpose() + b);
|
||||
VERIFY_RAISES_ASSERT(a = b + a.transpose());
|
||||
VERIFY_RAISES_ASSERT(a = a.conjugate().transpose());
|
||||
VERIFY_RAISES_ASSERT(a = a.adjoint());
|
||||
VERIFY_RAISES_ASSERT(a = a.adjoint() + b);
|
||||
VERIFY_RAISES_ASSERT(a = b + a.adjoint());
|
||||
|
||||
// no assertion should be triggered for these cases:
|
||||
a.transpose() = a.transpose();
|
||||
a.transpose() += a.transpose();
|
||||
a.transpose() += a.transpose() + b;
|
||||
a.transpose() = a.adjoint();
|
||||
a.transpose() += a.adjoint();
|
||||
a.transpose() += a.adjoint() + b;
|
||||
|
||||
// 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);
|
||||
|
||||
// regression for bug 1646
|
||||
for (int j = 0; j < 10; ++j) {
|
||||
c.col(j).head(j) = c.row(j).head(j);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 10; ++j) {
|
||||
c.col(j) = c.row(j);
|
||||
}
|
||||
|
||||
a.conservativeResize(1,1);
|
||||
a = a.transpose();
|
||||
|
||||
a.conservativeResize(0,0);
|
||||
a = a.transpose();
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(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(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>()) );
|
||||
|
||||
CALL_SUBTEST_13( adjoint_extra<0>() );
|
||||
}
|
||||
|
||||
710
libs/eigen/test/array_cwise.cpp
Normal file
710
libs/eigen/test/array_cwise.cpp
Normal file
@@ -0,0 +1,710 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 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"
|
||||
|
||||
|
||||
// Test the corner cases of pow(x, y) for real types.
|
||||
template<typename Scalar>
|
||||
void pow_test() {
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar eps = Eigen::NumTraits<Scalar>::epsilon();
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar two = Scalar(2);
|
||||
const Scalar three = Scalar(3);
|
||||
const Scalar sqrt_half = Scalar(std::sqrt(0.5));
|
||||
const Scalar sqrt2 = Scalar(std::sqrt(2));
|
||||
const Scalar inf = Eigen::NumTraits<Scalar>::infinity();
|
||||
const Scalar nan = Eigen::NumTraits<Scalar>::quiet_NaN();
|
||||
const Scalar denorm_min = std::numeric_limits<Scalar>::denorm_min();
|
||||
const Scalar min = (std::numeric_limits<Scalar>::min)();
|
||||
const Scalar max = (std::numeric_limits<Scalar>::max)();
|
||||
const Scalar max_exp = (static_cast<Scalar>(int(Eigen::NumTraits<Scalar>::max_exponent())) * Scalar(EIGEN_LN2)) / eps;
|
||||
|
||||
const static Scalar abs_vals[] = {zero,
|
||||
denorm_min,
|
||||
min,
|
||||
eps,
|
||||
sqrt_half,
|
||||
one,
|
||||
sqrt2,
|
||||
two,
|
||||
three,
|
||||
max_exp,
|
||||
max,
|
||||
inf,
|
||||
nan};
|
||||
const int abs_cases = 13;
|
||||
const int num_cases = 2*abs_cases * 2*abs_cases;
|
||||
// Repeat the same value to make sure we hit the vectorized path.
|
||||
const int num_repeats = 32;
|
||||
Array<Scalar, Dynamic, Dynamic> x(num_repeats, num_cases);
|
||||
Array<Scalar, Dynamic, Dynamic> y(num_repeats, num_cases);
|
||||
int count = 0;
|
||||
for (int i = 0; i < abs_cases; ++i) {
|
||||
const Scalar abs_x = abs_vals[i];
|
||||
for (int sign_x = 0; sign_x < 2; ++sign_x) {
|
||||
Scalar x_case = sign_x == 0 ? -abs_x : abs_x;
|
||||
for (int j = 0; j < abs_cases; ++j) {
|
||||
const Scalar abs_y = abs_vals[j];
|
||||
for (int sign_y = 0; sign_y < 2; ++sign_y) {
|
||||
Scalar y_case = sign_y == 0 ? -abs_y : abs_y;
|
||||
for (int repeat = 0; repeat < num_repeats; ++repeat) {
|
||||
x(repeat, count) = x_case;
|
||||
y(repeat, count) = y_case;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Array<Scalar, Dynamic, Dynamic> actual = x.pow(y);
|
||||
const Scalar tol = test_precision<Scalar>();
|
||||
bool all_pass = true;
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
for (int j = 0; j < num_cases; ++j) {
|
||||
Scalar e = static_cast<Scalar>(std::pow(x(i,j), y(i,j)));
|
||||
Scalar a = actual(i, j);
|
||||
bool fail = !(a==e) && !internal::isApprox(a, e, tol) && !((numext::isnan)(a) && (numext::isnan)(e));
|
||||
all_pass &= !fail;
|
||||
if (fail) {
|
||||
std::cout << "pow(" << x(i,j) << "," << y(i,j) << ") = " << a << " != " << e << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
VERIFY(all_pass);
|
||||
}
|
||||
|
||||
template<typename ArrayType> void array(const ArrayType& m)
|
||||
{
|
||||
typedef typename ArrayType::Scalar Scalar;
|
||||
typedef typename ArrayType::RealScalar RealScalar;
|
||||
typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
|
||||
typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
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);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>(),
|
||||
s2 = internal::random<Scalar>();
|
||||
|
||||
// scalar addition
|
||||
VERIFY_IS_APPROX(m1 + s1, s1 + m1);
|
||||
VERIFY_IS_APPROX(m1 + s1, ArrayType::Constant(rows,cols,s1) + m1);
|
||||
VERIFY_IS_APPROX(s1 - m1, (-m1)+s1 );
|
||||
VERIFY_IS_APPROX(m1 - s1, m1 - ArrayType::Constant(rows,cols,s1));
|
||||
VERIFY_IS_APPROX(s1 - m1, ArrayType::Constant(rows,cols,s1) - m1);
|
||||
VERIFY_IS_APPROX((m1*Scalar(2)) - s2, (m1+m1) - ArrayType::Constant(rows,cols,s2) );
|
||||
m3 = m1;
|
||||
m3 += s2;
|
||||
VERIFY_IS_APPROX(m3, m1 + s2);
|
||||
m3 = m1;
|
||||
m3 -= s1;
|
||||
VERIFY_IS_APPROX(m3, m1 - s1);
|
||||
|
||||
// scalar operators via Maps
|
||||
m3 = m1;
|
||||
ArrayType::Map(m1.data(), m1.rows(), m1.cols()) -= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m1, m3 - m2);
|
||||
|
||||
m3 = m1;
|
||||
ArrayType::Map(m1.data(), m1.rows(), m1.cols()) += ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m1, m3 + m2);
|
||||
|
||||
m3 = m1;
|
||||
ArrayType::Map(m1.data(), m1.rows(), m1.cols()) *= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m1, m3 * m2);
|
||||
|
||||
m3 = m1;
|
||||
m2 = ArrayType::Random(rows,cols);
|
||||
m2 = (m2==0).select(1,m2);
|
||||
ArrayType::Map(m1.data(), m1.rows(), m1.cols()) /= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
|
||||
VERIFY_IS_APPROX(m1, m3 / m2);
|
||||
|
||||
// reductions
|
||||
VERIFY_IS_APPROX(m1.abs().colwise().sum().sum(), m1.abs().sum());
|
||||
VERIFY_IS_APPROX(m1.abs().rowwise().sum().sum(), m1.abs().sum());
|
||||
using std::abs;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.colwise().sum().sum() - m1.sum()), m1.abs().sum());
|
||||
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,Scalar>()));
|
||||
|
||||
// vector-wise ops
|
||||
m3 = m1;
|
||||
VERIFY_IS_APPROX(m3.colwise() += cv1, m1.colwise() + cv1);
|
||||
m3 = m1;
|
||||
VERIFY_IS_APPROX(m3.colwise() -= cv1, m1.colwise() - cv1);
|
||||
m3 = m1;
|
||||
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);
|
||||
}
|
||||
#if EIGEN_HAS_CXX11
|
||||
{
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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 o2(static_cast<int>(rows));
|
||||
VERIFY(o2.size()==rows);
|
||||
}
|
||||
#if EIGEN_HAS_CXX11
|
||||
{
|
||||
OneDArrayType o1{rows};
|
||||
VERIFY(o1.size()==rows);
|
||||
OneDArrayType o4{int(rows)};
|
||||
VERIFY(o4.size()==rows);
|
||||
}
|
||||
#endif
|
||||
// Check possible conflicts with 2D ctor
|
||||
typedef Array<Scalar, Dynamic, Dynamic> TwoDArrayType;
|
||||
typedef Array<Scalar, 2, 1> ArrayType2;
|
||||
{
|
||||
TwoDArrayType o1(rows,cols);
|
||||
VERIFY(o1.rows()==rows);
|
||||
VERIFY(o1.cols()==cols);
|
||||
TwoDArrayType o2(static_cast<int>(rows),static_cast<int>(cols));
|
||||
VERIFY(o2.rows()==rows);
|
||||
VERIFY(o2.cols()==cols);
|
||||
|
||||
ArrayType2 o3(rows,cols);
|
||||
VERIFY(o3(0)==Scalar(rows) && o3(1)==Scalar(cols));
|
||||
ArrayType2 o4(static_cast<int>(rows),static_cast<int>(cols));
|
||||
VERIFY(o4(0)==Scalar(rows) && o4(1)==Scalar(cols));
|
||||
}
|
||||
#if EIGEN_HAS_CXX11
|
||||
{
|
||||
TwoDArrayType o1{rows,cols};
|
||||
VERIFY(o1.rows()==rows);
|
||||
VERIFY(o1.cols()==cols);
|
||||
TwoDArrayType o2{int(rows),int(cols)};
|
||||
VERIFY(o2.rows()==rows);
|
||||
VERIFY(o2.cols()==cols);
|
||||
|
||||
ArrayType2 o3{rows,cols};
|
||||
VERIFY(o3(0)==Scalar(rows) && o3(1)==Scalar(cols));
|
||||
ArrayType2 o4{int(rows),int(cols)};
|
||||
VERIFY(o4(0)==Scalar(rows) && o4(1)==Scalar(cols));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename ArrayType> void comparisons(const ArrayType& m)
|
||||
{
|
||||
using std::abs;
|
||||
typedef typename ArrayType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
Index r = internal::random<Index>(0, rows-1),
|
||||
c = internal::random<Index>(0, cols-1);
|
||||
|
||||
ArrayType m1 = ArrayType::Random(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());
|
||||
if (rows*cols>1)
|
||||
{
|
||||
m3 = m1;
|
||||
m3(r,c) += 1;
|
||||
VERIFY(! (m1 < m3).all() );
|
||||
VERIFY(! (m1 > m3).all() );
|
||||
}
|
||||
VERIFY(!(m1 > m2 && m1 < m2).any());
|
||||
VERIFY((m1 <= m2 || m1 >= m2).all());
|
||||
|
||||
// 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() );
|
||||
|
||||
// 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) );
|
||||
VERIFY_IS_APPROX( (m1>m2).select(m1,m2), m1.cwiseMax(m2) );
|
||||
Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
|
||||
for (int j=0; j<cols; ++j)
|
||||
for (int i=0; i<rows; ++i)
|
||||
m3(i,j) = abs(m1(i,j))<mid ? 0 : m1(i,j);
|
||||
VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
|
||||
.select(ArrayType::Zero(rows,cols),m1), m3);
|
||||
// shorter versions:
|
||||
VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
|
||||
.select(0,m1), m3);
|
||||
VERIFY_IS_APPROX( (m1.abs()>=ArrayType::Constant(rows,cols,mid))
|
||||
.select(m1,0), m3);
|
||||
// even shorter version:
|
||||
VERIFY_IS_APPROX( (m1.abs()<mid).select(0,m1), m3);
|
||||
|
||||
// count
|
||||
VERIFY(((m1.abs()+1)>RealScalar(0.1)).count() == rows*cols);
|
||||
|
||||
// and/or
|
||||
VERIFY( (m1<RealScalar(0) && m1>RealScalar(0)).count() == 0);
|
||||
VERIFY( (m1<RealScalar(0) || m1>=RealScalar(0)).count() == rows*cols);
|
||||
RealScalar a = m1.abs().mean();
|
||||
VERIFY( (m1<-a || m1>a).count() == (m1.abs()>a).count());
|
||||
|
||||
typedef Array<Index, Dynamic, 1> ArrayOfIndices;
|
||||
|
||||
// TODO allows colwise/rowwise for array
|
||||
VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).colwise().count(), ArrayOfIndices::Constant(cols,rows).transpose());
|
||||
VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).rowwise().count(), ArrayOfIndices::Constant(rows, cols));
|
||||
}
|
||||
|
||||
template<typename ArrayType> void array_real(const ArrayType& m)
|
||||
{
|
||||
using std::abs;
|
||||
using std::sqrt;
|
||||
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 = ArrayType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
m4 = m1;
|
||||
|
||||
m4 = (m4.abs()==Scalar(0)).select(Scalar(1),m4);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
|
||||
// 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.atan(), atan(m1));
|
||||
VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
|
||||
VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
|
||||
VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
|
||||
#if EIGEN_HAS_CXX11_MATH
|
||||
VERIFY_IS_APPROX(m1.tanh().atanh(), atanh(tanh(m1)));
|
||||
VERIFY_IS_APPROX(m1.sinh().asinh(), asinh(sinh(m1)));
|
||||
VERIFY_IS_APPROX(m1.cosh().acosh(), acosh(cosh(m1)));
|
||||
#endif
|
||||
VERIFY_IS_APPROX(m1.logistic(), logistic(m1));
|
||||
|
||||
VERIFY_IS_APPROX(m1.arg(), arg(m1));
|
||||
VERIFY_IS_APPROX(m1.round(), round(m1));
|
||||
VERIFY_IS_APPROX(m1.rint(), rint(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(m4.inverse(), inverse(m4));
|
||||
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((m1.sqrt().sign().isNaN() == (Eigen::isnan)(sign(sqrt(m1)))).all());
|
||||
|
||||
// avoid inf and NaNs so verification doesn't fail
|
||||
m3 = m4.abs();
|
||||
VERIFY_IS_APPROX(m3.sqrt(), sqrt(abs(m3)));
|
||||
VERIFY_IS_APPROX(m3.rsqrt(), Scalar(1)/sqrt(abs(m3)));
|
||||
VERIFY_IS_APPROX(rsqrt(m3), Scalar(1)/sqrt(abs(m3)));
|
||||
VERIFY_IS_APPROX(m3.log(), log(m3));
|
||||
VERIFY_IS_APPROX(m3.log1p(), log1p(m3));
|
||||
VERIFY_IS_APPROX(m3.log10(), log10(m3));
|
||||
VERIFY_IS_APPROX(m3.log2(), log2(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), Scalar(0.5)*(exp(m1)-exp(-m1)));
|
||||
VERIFY_IS_APPROX(cosh(m1), Scalar(0.5)*(exp(m1)+exp(-m1)));
|
||||
VERIFY_IS_APPROX(tanh(m1), (Scalar(0.5)*(exp(m1)-exp(-m1)))/(Scalar(0.5)*(exp(m1)+exp(-m1))));
|
||||
VERIFY_IS_APPROX(logistic(m1), (Scalar(1)/(Scalar(1)+exp(-m1))));
|
||||
VERIFY_IS_APPROX(arg(m1), ((m1<Scalar(0)).template cast<Scalar>())*Scalar(std::acos(Scalar(-1))));
|
||||
VERIFY((round(m1) <= ceil(m1) && round(m1) >= floor(m1)).all());
|
||||
VERIFY((rint(m1) <= ceil(m1) && rint(m1) >= floor(m1)).all());
|
||||
VERIFY(((ceil(m1) - round(m1)) <= Scalar(0.5) || (round(m1) - floor(m1)) <= Scalar(0.5)).all());
|
||||
VERIFY(((ceil(m1) - round(m1)) <= Scalar(1.0) && (round(m1) - floor(m1)) <= Scalar(1.0)).all());
|
||||
VERIFY(((ceil(m1) - rint(m1)) <= Scalar(0.5) || (rint(m1) - floor(m1)) <= Scalar(0.5)).all());
|
||||
VERIFY(((ceil(m1) - rint(m1)) <= Scalar(1.0) && (rint(m1) - floor(m1)) <= Scalar(1.0)).all());
|
||||
VERIFY((Eigen::isnan)((m1*Scalar(0))/Scalar(0)).all());
|
||||
VERIFY((Eigen::isinf)(m4/Scalar(0)).all());
|
||||
VERIFY(((Eigen::isfinite)(m1) && (!(Eigen::isfinite)(m1*Scalar(0)/Scalar(0))) && (!(Eigen::isfinite)(m4/Scalar(0)))).all());
|
||||
VERIFY_IS_APPROX(inverse(inverse(m4)),m4);
|
||||
VERIFY((abs(m1) == m1 || abs(m1) == -m1).all());
|
||||
VERIFY_IS_APPROX(m3, sqrt(abs2(m3)));
|
||||
VERIFY_IS_APPROX(m1.absolute_difference(m2), (m1 > m2).select(m1 - m2, m2 - 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(Eigen::real(m1)) + numext::abs2(Eigen::imag(m1)), numext::abs2(m1));
|
||||
if(!NumTraits<Scalar>::IsComplex)
|
||||
VERIFY_IS_APPROX(numext::real(m1), m1);
|
||||
|
||||
// shift argument of logarithm so that it is not zero
|
||||
Scalar smallNumber = NumTraits<Scalar>::dummy_precision();
|
||||
VERIFY_IS_APPROX((m3 + smallNumber).log() , log(abs(m3) + smallNumber));
|
||||
VERIFY_IS_APPROX((m3 + smallNumber + Scalar(1)).log() , log1p(abs(m3) + 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.expm1(), expm1(m1));
|
||||
VERIFY_IS_APPROX((m3 + smallNumber).exp() - Scalar(1), expm1(abs(m3) + smallNumber));
|
||||
|
||||
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());
|
||||
|
||||
// Avoid inf and NaN.
|
||||
m3 = (m1.square()<NumTraits<Scalar>::epsilon()).select(Scalar(1),m3);
|
||||
VERIFY_IS_APPROX(m3.pow(RealScalar(-2)), m3.square().inverse());
|
||||
pow_test<Scalar>();
|
||||
|
||||
VERIFY_IS_APPROX(log10(m3), log(m3)/numext::log(Scalar(10)));
|
||||
VERIFY_IS_APPROX(log2(m3), log(m3)/numext::log(Scalar(2)));
|
||||
|
||||
// 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());
|
||||
m3.transposeInPlace();
|
||||
VERIFY_IS_APPROX(m3, m1);
|
||||
}
|
||||
|
||||
template<typename ArrayType> void array_complex(const ArrayType& m)
|
||||
{
|
||||
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),
|
||||
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));
|
||||
|
||||
// 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.logistic(), logistic(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(m4.inverse(), inverse(m4));
|
||||
VERIFY_IS_APPROX(m1.log(), log(m1));
|
||||
VERIFY_IS_APPROX(m1.log10(), log10(m1));
|
||||
VERIFY_IS_APPROX(m1.log2(), log2(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(m1.expm1(), expm1(m1));
|
||||
VERIFY_IS_APPROX(expm1(m1), exp(m1) - 1.);
|
||||
// Check for larger magnitude complex numbers that expm1 matches exp - 1.
|
||||
VERIFY_IS_APPROX(expm1(10. * m1), exp(10. * m1) - 1.);
|
||||
|
||||
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(logistic(m1), (1.0/(1.0 + exp(-m1))));
|
||||
|
||||
for (Index i = 0; i < m.rows(); ++i)
|
||||
for (Index j = 0; j < m.cols(); ++j)
|
||||
m3(i,j) = std::atan2(m1(i,j).imag(), m1(i,j).real());
|
||||
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(m4)),m4);
|
||||
VERIFY_IS_APPROX(conj(m1.conjugate()), m1);
|
||||
VERIFY_IS_APPROX(abs(m1), sqrt(square(m1.real())+square(m1.imag())));
|
||||
VERIFY_IS_APPROX(abs(m1), sqrt(abs2(m1)));
|
||||
VERIFY_IS_APPROX(log10(m1), log(m1)/log(10));
|
||||
VERIFY_IS_APPROX(log2(m1), log(m1)/log(2));
|
||||
|
||||
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);
|
||||
// Check vectorized inplace transpose.
|
||||
ArrayType m5 = ArrayType::Random(131, 131);
|
||||
ArrayType m6 = m5;
|
||||
m6.transposeInPlace();
|
||||
VERIFY_IS_APPROX(m6, m5.transpose());
|
||||
}
|
||||
|
||||
template<typename ArrayType> void min_max(const ArrayType& m)
|
||||
{
|
||||
typedef typename ArrayType::Scalar Scalar;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
ArrayType m1 = ArrayType::Random(rows, cols);
|
||||
|
||||
// min/max with array
|
||||
Scalar maxM1 = m1.maxCoeff();
|
||||
Scalar minM1 = m1.minCoeff();
|
||||
|
||||
VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, minM1), (m1.min)(ArrayType::Constant(rows,cols, minM1)));
|
||||
VERIFY_IS_APPROX(m1, (m1.min)(ArrayType::Constant(rows,cols, maxM1)));
|
||||
|
||||
VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)(ArrayType::Constant(rows,cols, maxM1)));
|
||||
VERIFY_IS_APPROX(m1, (m1.max)(ArrayType::Constant(rows,cols, minM1)));
|
||||
|
||||
// min/max with scalar input
|
||||
VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, minM1), (m1.min)( minM1));
|
||||
VERIFY_IS_APPROX(m1, (m1.min)( maxM1));
|
||||
|
||||
VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)( maxM1));
|
||||
VERIFY_IS_APPROX(m1, (m1.max)( minM1));
|
||||
|
||||
|
||||
// min/max with various NaN propagation options.
|
||||
if (m1.size() > 1 && !NumTraits<Scalar>::IsInteger) {
|
||||
m1(0,0) = NumTraits<Scalar>::quiet_NaN();
|
||||
maxM1 = m1.template maxCoeff<PropagateNaN>();
|
||||
minM1 = m1.template minCoeff<PropagateNaN>();
|
||||
VERIFY((numext::isnan)(maxM1));
|
||||
VERIFY((numext::isnan)(minM1));
|
||||
|
||||
maxM1 = m1.template maxCoeff<PropagateNumbers>();
|
||||
minM1 = m1.template minCoeff<PropagateNumbers>();
|
||||
VERIFY(!(numext::isnan)(maxM1));
|
||||
VERIFY(!(numext::isnan)(minM1));
|
||||
}
|
||||
}
|
||||
|
||||
template<int N>
|
||||
struct shift_left {
|
||||
template<typename Scalar>
|
||||
Scalar operator()(const Scalar& v) const {
|
||||
return v << N;
|
||||
}
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct arithmetic_shift_right {
|
||||
template<typename Scalar>
|
||||
Scalar operator()(const Scalar& v) const {
|
||||
return v >> N;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ArrayType> void array_integer(const ArrayType& m)
|
||||
{
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
ArrayType m1 = ArrayType::Random(rows, cols),
|
||||
m2(rows, cols);
|
||||
|
||||
m2 = m1.template shiftLeft<2>();
|
||||
VERIFY( (m2 == m1.unaryExpr(shift_left<2>())).all() );
|
||||
m2 = m1.template shiftLeft<9>();
|
||||
VERIFY( (m2 == m1.unaryExpr(shift_left<9>())).all() );
|
||||
|
||||
m2 = m1.template shiftRight<2>();
|
||||
VERIFY( (m2 == m1.unaryExpr(arithmetic_shift_right<2>())).all() );
|
||||
m2 = m1.template shiftRight<9>();
|
||||
VERIFY( (m2 == m1.unaryExpr(arithmetic_shift_right<9>())).all() );
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(array_cwise)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( array(Array<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( array(Array22f()) );
|
||||
CALL_SUBTEST_3( array(Array44d()) );
|
||||
CALL_SUBTEST_4( array(ArrayXXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_5( array(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( array(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( array(Array<Index,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( array_integer(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( array_integer(Array<Index,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( comparisons(Array<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( comparisons(Array22f()) );
|
||||
CALL_SUBTEST_3( comparisons(Array44d()) );
|
||||
CALL_SUBTEST_5( comparisons(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( comparisons(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( min_max(Array<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( min_max(Array22f()) );
|
||||
CALL_SUBTEST_3( min_max(Array44d()) );
|
||||
CALL_SUBTEST_5( min_max(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( min_max(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( array_real(Array<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( array_real(Array22f()) );
|
||||
CALL_SUBTEST_3( array_real(Array44d()) );
|
||||
CALL_SUBTEST_5( array_real(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_7( array_real(Array<Eigen::half, 32, 32>()) );
|
||||
CALL_SUBTEST_8( array_real(Array<Eigen::bfloat16, 32, 32>()) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_4( array_complex(ArrayXXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
|
||||
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_abs_op<double>, ArrayXd > Xpr;
|
||||
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Xpr>::type,
|
||||
ArrayBase<Xpr>
|
||||
>::value));
|
||||
}
|
||||
307
libs/eigen/test/array_for_matrix.cpp
Normal file
307
libs/eigen/test/array_for_matrix.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 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"
|
||||
|
||||
template<typename MatrixType> void array_for_matrix(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
|
||||
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols);
|
||||
|
||||
ColVectorType cv1 = ColVectorType::Random(rows);
|
||||
RowVectorType rv1 = RowVectorType::Random(cols);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>(),
|
||||
s2 = internal::random<Scalar>();
|
||||
|
||||
// scalar addition
|
||||
VERIFY_IS_APPROX(m1.array() + s1, s1 + m1.array());
|
||||
VERIFY_IS_APPROX((m1.array() + s1).matrix(), MatrixType::Constant(rows,cols,s1) + m1);
|
||||
VERIFY_IS_APPROX(((m1*Scalar(2)).array() - s2).matrix(), (m1+m1) - MatrixType::Constant(rows,cols,s2) );
|
||||
m3 = m1;
|
||||
m3.array() += s2;
|
||||
VERIFY_IS_APPROX(m3, (m1.array() + s2).matrix());
|
||||
m3 = m1;
|
||||
m3.array() -= s1;
|
||||
VERIFY_IS_APPROX(m3, (m1.array() - s1).matrix());
|
||||
|
||||
// reductions
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(m1.colwise().sum().sum() - m1.sum(), m1.squaredNorm());
|
||||
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,Scalar>()));
|
||||
|
||||
// vector-wise ops
|
||||
m3 = m1;
|
||||
VERIFY_IS_APPROX(m3.colwise() += cv1, m1.colwise() + cv1);
|
||||
m3 = m1;
|
||||
VERIFY_IS_APPROX(m3.colwise() -= cv1, m1.colwise() - cv1);
|
||||
m3 = m1;
|
||||
VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
|
||||
m3 = m1;
|
||||
VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
|
||||
|
||||
// empty objects
|
||||
VERIFY_IS_APPROX((m1.template block<0,Dynamic>(0,0,0,cols).colwise().sum()), RowVectorType::Zero(cols));
|
||||
VERIFY_IS_APPROX((m1.template block<Dynamic,0>(0,0,rows,0).rowwise().sum()), ColVectorType::Zero(rows));
|
||||
VERIFY_IS_APPROX((m1.template block<0,Dynamic>(0,0,0,cols).colwise().prod()), RowVectorType::Ones(cols));
|
||||
VERIFY_IS_APPROX((m1.template block<Dynamic,0>(0,0,rows,0).rowwise().prod()), ColVectorType::Ones(rows));
|
||||
|
||||
VERIFY_IS_APPROX(m1.block(0,0,0,cols).colwise().sum(), RowVectorType::Zero(cols));
|
||||
VERIFY_IS_APPROX(m1.block(0,0,rows,0).rowwise().sum(), ColVectorType::Zero(rows));
|
||||
VERIFY_IS_APPROX(m1.block(0,0,0,cols).colwise().prod(), RowVectorType::Ones(cols));
|
||||
VERIFY_IS_APPROX(m1.block(0,0,rows,0).rowwise().prod(), ColVectorType::Ones(rows));
|
||||
|
||||
// verify the const accessors exist
|
||||
const Scalar& ref_m1 = m.matrix().array().coeffRef(0);
|
||||
const Scalar& ref_m2 = m.matrix().array().coeffRef(0,0);
|
||||
const Scalar& ref_a1 = m.array().matrix().coeffRef(0);
|
||||
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)
|
||||
{
|
||||
using std::abs;
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
Index r = internal::random<Index>(0, rows-1),
|
||||
c = internal::random<Index>(0, cols-1);
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols);
|
||||
|
||||
VERIFY(((m1.array() + Scalar(1)) > m1.array()).all());
|
||||
VERIFY(((m1.array() - Scalar(1)) < m1.array()).all());
|
||||
if (rows*cols>1)
|
||||
{
|
||||
m3 = m1;
|
||||
m3(r,c) += 1;
|
||||
VERIFY(! (m1.array() < m3.array()).all() );
|
||||
VERIFY(! (m1.array() > m3.array()).all() );
|
||||
}
|
||||
|
||||
// comparisons to scalar
|
||||
VERIFY( (m1.array() != (m1(r,c)+1) ).any() );
|
||||
VERIFY( (m1.array() > (m1(r,c)-1) ).any() );
|
||||
VERIFY( (m1.array() < (m1(r,c)+1) ).any() );
|
||||
VERIFY( (m1.array() == m1(r,c) ).any() );
|
||||
VERIFY( m1.cwiseEqual(m1(r,c)).any() );
|
||||
|
||||
// test Select
|
||||
VERIFY_IS_APPROX( (m1.array()<m2.array()).select(m1,m2), m1.cwiseMin(m2) );
|
||||
VERIFY_IS_APPROX( (m1.array()>m2.array()).select(m1,m2), m1.cwiseMax(m2) );
|
||||
Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
|
||||
for (int j=0; j<cols; ++j)
|
||||
for (int i=0; i<rows; ++i)
|
||||
m3(i,j) = abs(m1(i,j))<mid ? 0 : m1(i,j);
|
||||
VERIFY_IS_APPROX( (m1.array().abs()<MatrixType::Constant(rows,cols,mid).array())
|
||||
.select(MatrixType::Zero(rows,cols),m1), m3);
|
||||
// shorter versions:
|
||||
VERIFY_IS_APPROX( (m1.array().abs()<MatrixType::Constant(rows,cols,mid).array())
|
||||
.select(0,m1), m3);
|
||||
VERIFY_IS_APPROX( (m1.array().abs()>=MatrixType::Constant(rows,cols,mid).array())
|
||||
.select(m1,0), m3);
|
||||
// even shorter version:
|
||||
VERIFY_IS_APPROX( (m1.array().abs()<mid).select(0,m1), m3);
|
||||
|
||||
// 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<Index, Dynamic, 1> VectorOfIndices;
|
||||
|
||||
// TODO allows colwise/rowwise for array
|
||||
VERIFY_IS_APPROX(((m1.array().abs()+1)>RealScalar(0.1)).matrix().colwise().count(), VectorOfIndices::Constant(cols,rows).transpose());
|
||||
VERIFY_IS_APPROX(((m1.array().abs()+1)>RealScalar(0.1)).matrix().rowwise().count(), VectorOfIndices::Constant(rows, cols));
|
||||
}
|
||||
|
||||
template<typename VectorType> void lpNorm(const VectorType& v)
|
||||
{
|
||||
using std::sqrt;
|
||||
typedef typename VectorType::RealScalar RealScalar;
|
||||
VectorType u = VectorType::Random(v.size());
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
template<typename MatrixType> void cwise_min_max(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols);
|
||||
|
||||
// min/max with array
|
||||
Scalar maxM1 = m1.maxCoeff();
|
||||
Scalar minM1 = m1.minCoeff();
|
||||
|
||||
VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, minM1), m1.cwiseMin(MatrixType::Constant(rows,cols, minM1)));
|
||||
VERIFY_IS_APPROX(m1, m1.cwiseMin(MatrixType::Constant(rows,cols, maxM1)));
|
||||
|
||||
VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, maxM1), m1.cwiseMax(MatrixType::Constant(rows,cols, maxM1)));
|
||||
VERIFY_IS_APPROX(m1, m1.cwiseMax(MatrixType::Constant(rows,cols, minM1)));
|
||||
|
||||
// min/max with scalar input
|
||||
VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, minM1), m1.cwiseMin( minM1));
|
||||
VERIFY_IS_APPROX(m1, m1.cwiseMin(maxM1));
|
||||
VERIFY_IS_APPROX(-m1, (-m1).cwiseMin(-minM1));
|
||||
VERIFY_IS_APPROX(-m1.array(), ((-m1).array().min)( -minM1));
|
||||
|
||||
VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, maxM1), m1.cwiseMax( maxM1));
|
||||
VERIFY_IS_APPROX(m1, m1.cwiseMax(minM1));
|
||||
VERIFY_IS_APPROX(-m1, (-m1).cwiseMax(-maxM1));
|
||||
VERIFY_IS_APPROX(-m1.array(), ((-m1).array().max)(-maxM1));
|
||||
|
||||
VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, minM1).array(), (m1.array().min)( minM1));
|
||||
VERIFY_IS_APPROX(m1.array(), (m1.array().min)( maxM1));
|
||||
|
||||
VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, maxM1).array(), (m1.array().max)( maxM1));
|
||||
VERIFY_IS_APPROX(m1.array(), (m1.array().max)( minM1));
|
||||
|
||||
}
|
||||
|
||||
template<typename MatrixTraits> void resize(const MatrixTraits& t)
|
||||
{
|
||||
typedef typename MatrixTraits::Scalar Scalar;
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType;
|
||||
typedef Array<Scalar,Dynamic,Dynamic> Array2DType;
|
||||
typedef Matrix<Scalar,Dynamic,1> VectorType;
|
||||
typedef Array<Scalar,Dynamic,1> Array1DType;
|
||||
|
||||
Index rows = t.rows(), cols = t.cols();
|
||||
|
||||
MatrixType m(rows,cols);
|
||||
VectorType v(rows);
|
||||
Array2DType a2(rows,cols);
|
||||
Array1DType a1(rows);
|
||||
|
||||
m.array().resize(rows+1,cols+1);
|
||||
VERIFY(m.rows()==rows+1 && m.cols()==cols+1);
|
||||
a2.matrix().resize(rows+1,cols+1);
|
||||
VERIFY(a2.rows()==rows+1 && a2.cols()==cols+1);
|
||||
v.array().resize(cols);
|
||||
VERIFY(v.size()==cols);
|
||||
a1.matrix().resize(cols);
|
||||
VERIFY(a1.size()==cols);
|
||||
}
|
||||
|
||||
template<int>
|
||||
void regression_bug_654()
|
||||
{
|
||||
ArrayXf a = RowVectorXf(3);
|
||||
VectorXf v = Array<float,1,Dynamic>(3);
|
||||
}
|
||||
|
||||
// Check propagation of LvalueBit through Array/Matrix-Wrapper
|
||||
template<int>
|
||||
void regrrssion_bug_1410()
|
||||
{
|
||||
const Matrix4i M;
|
||||
const Array4i A;
|
||||
ArrayWrapper<const Matrix4i> MA = M.array();
|
||||
MA.row(0);
|
||||
MatrixWrapper<const Array4i> AM = A.matrix();
|
||||
AM.row(0);
|
||||
|
||||
VERIFY((internal::traits<ArrayWrapper<const Matrix4i> >::Flags&LvalueBit)==0);
|
||||
VERIFY((internal::traits<MatrixWrapper<const Array4i> >::Flags&LvalueBit)==0);
|
||||
|
||||
VERIFY((internal::traits<ArrayWrapper<Matrix4i> >::Flags&LvalueBit)==LvalueBit);
|
||||
VERIFY((internal::traits<MatrixWrapper<Array4i> >::Flags&LvalueBit)==LvalueBit);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(array_for_matrix)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( array_for_matrix(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( array_for_matrix(Matrix2f()) );
|
||||
CALL_SUBTEST_3( array_for_matrix(Matrix4d()) );
|
||||
CALL_SUBTEST_4( array_for_matrix(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_5( array_for_matrix(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( array_for_matrix(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
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(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( comparisons(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( cwise_min_max(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( cwise_min_max(Matrix2f()) );
|
||||
CALL_SUBTEST_3( cwise_min_max(Matrix4d()) );
|
||||
CALL_SUBTEST_5( cwise_min_max(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( cwise_min_max(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( lpNorm(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( lpNorm(Vector2f()) );
|
||||
CALL_SUBTEST_7( lpNorm(Vector3d()) );
|
||||
CALL_SUBTEST_8( lpNorm(Vector4f()) );
|
||||
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))) );
|
||||
CALL_SUBTEST_6( resize(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
CALL_SUBTEST_6( regression_bug_654<0>() );
|
||||
CALL_SUBTEST_6( regrrssion_bug_1410<0>() );
|
||||
}
|
||||
32
libs/eigen/test/array_of_string.cpp
Normal file
32
libs/eigen/test/array_of_string.cpp
Normal file
@@ -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"
|
||||
|
||||
EIGEN_DECLARE_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());
|
||||
}
|
||||
81
libs/eigen/test/array_replicate.cpp
Normal file
81
libs/eigen/test/array_replicate.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 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"
|
||||
|
||||
template<typename MatrixType> void replicate(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Replicate.cpp
|
||||
*/
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic> MatrixX;
|
||||
typedef Matrix<Scalar, Dynamic, 1> VectorX;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols);
|
||||
|
||||
VectorType v1 = VectorType::Random(rows);
|
||||
|
||||
MatrixX x1, x2;
|
||||
VectorX vx1;
|
||||
|
||||
int f1 = internal::random<int>(1,10),
|
||||
f2 = internal::random<int>(1,10);
|
||||
|
||||
x1.resize(rows*f1,cols*f2);
|
||||
for(int j=0; j<f2; j++)
|
||||
for(int i=0; i<f1; i++)
|
||||
x1.block(i*rows,j*cols,rows,cols) = m1;
|
||||
VERIFY_IS_APPROX(x1, m1.replicate(f1,f2));
|
||||
|
||||
x2.resize(2*rows,3*cols);
|
||||
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)
|
||||
x2.col(j) = v1;
|
||||
VERIFY_IS_APPROX(x2, v1.rowwise().replicate(f1));
|
||||
|
||||
vx1.resize(rows*f2);
|
||||
for (int j=0; j<f2; ++j)
|
||||
vx1.segment(j*rows,rows) = v1;
|
||||
VERIFY_IS_APPROX(vx1, v1.colwise().replicate(f2));
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(array_replicate)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( replicate(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( replicate(Vector2f()) );
|
||||
CALL_SUBTEST_3( replicate(Vector3d()) );
|
||||
CALL_SUBTEST_4( replicate(Vector4f()) );
|
||||
CALL_SUBTEST_5( replicate(VectorXf(16)) );
|
||||
CALL_SUBTEST_6( replicate(VectorXcd(10)) );
|
||||
}
|
||||
}
|
||||
204
libs/eigen/test/array_reverse.cpp
Normal file
204
libs/eigen/test/array_reverse.cpp
Normal file
@@ -0,0 +1,204 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2009 Ricard Marxer <email@ricardmarxer.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 <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
template<typename MatrixType> void reverse(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index 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;
|
||||
VectorType v1 = VectorType::Random(rows);
|
||||
|
||||
MatrixType m1_r = m1.reverse();
|
||||
// Verify that MatrixBase::reverse() works
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
for ( int j = 0; j < cols; j++ ) {
|
||||
VERIFY_IS_APPROX(m1_r(i, j), m1(rows - 1 - i, cols - 1 - j));
|
||||
}
|
||||
}
|
||||
|
||||
Reverse<MatrixType> m1_rd(m1);
|
||||
// Verify that a Reverse default (in both directions) of an expression works
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
for ( int j = 0; j < cols; j++ ) {
|
||||
VERIFY_IS_APPROX(m1_rd(i, j), m1(rows - 1 - i, cols - 1 - j));
|
||||
}
|
||||
}
|
||||
|
||||
Reverse<MatrixType, BothDirections> m1_rb(m1);
|
||||
// Verify that a Reverse in both directions of an expression works
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
for ( int j = 0; j < cols; j++ ) {
|
||||
VERIFY_IS_APPROX(m1_rb(i, j), m1(rows - 1 - i, cols - 1 - j));
|
||||
}
|
||||
}
|
||||
|
||||
Reverse<MatrixType, Vertical> m1_rv(m1);
|
||||
// Verify that a Reverse in the vertical directions of an expression works
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
for ( int j = 0; j < cols; j++ ) {
|
||||
VERIFY_IS_APPROX(m1_rv(i, j), m1(rows - 1 - i, j));
|
||||
}
|
||||
}
|
||||
|
||||
Reverse<MatrixType, Horizontal> m1_rh(m1);
|
||||
// Verify that a Reverse in the horizontal directions of an expression works
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
for ( int j = 0; j < cols; j++ ) {
|
||||
VERIFY_IS_APPROX(m1_rh(i, j), m1(i, cols - 1 - j));
|
||||
}
|
||||
}
|
||||
|
||||
VectorType v1_r = v1.reverse();
|
||||
// Verify that a VectorType::reverse() of an expression works
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
VERIFY_IS_APPROX(v1_r(i), v1(rows - 1 - i));
|
||||
}
|
||||
|
||||
MatrixType m1_cr = m1.colwise().reverse();
|
||||
// Verify that PartialRedux::reverse() works (for colwise())
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
for ( int j = 0; j < cols; j++ ) {
|
||||
VERIFY_IS_APPROX(m1_cr(i, j), m1(rows - 1 - i, j));
|
||||
}
|
||||
}
|
||||
|
||||
MatrixType m1_rr = m1.rowwise().reverse();
|
||||
// Verify that PartialRedux::reverse() works (for rowwise())
|
||||
for ( int i = 0; i < rows; i++ ) {
|
||||
for ( int j = 0; j < cols; j++ ) {
|
||||
VERIFY_IS_APPROX(m1_rr(i, j), m1(i, cols - 1 - j));
|
||||
}
|
||||
}
|
||||
|
||||
Scalar x = internal::random<Scalar>();
|
||||
|
||||
Index r = internal::random<Index>(0, rows-1),
|
||||
c = internal::random<Index>(0, cols-1);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
template<int>
|
||||
void array_reverse_extra()
|
||||
{
|
||||
Vector4f x; x << 1, 2, 3, 4;
|
||||
Vector4f y; y << 4, 3, 2, 1;
|
||||
VERIFY(x.reverse()[1] == 3);
|
||||
VERIFY(x.reverse() == y);
|
||||
}
|
||||
|
||||
// Simpler version of reverseInPlace leveraging a bug
|
||||
// in clang 6/7 with -O2 and AVX or AVX512 enabled.
|
||||
// This simpler version ensure that the clang bug is not simply hidden
|
||||
// through mis-inlining of reverseInPlace or other minor changes.
|
||||
template<typename MatrixType>
|
||||
EIGEN_DONT_INLINE
|
||||
void bug1684_job1(MatrixType& m1, MatrixType& m2)
|
||||
{
|
||||
m2 = m1;
|
||||
m2.col(0).swap(m2.col(3));
|
||||
m2.col(1).swap(m2.col(2));
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
EIGEN_DONT_INLINE
|
||||
void bug1684_job2(MatrixType& m1, MatrixType& m2)
|
||||
{
|
||||
m2 = m1; // load m1/m2 in AVX registers
|
||||
m1.col(0) = m2.col(3); // perform 128 bits moves
|
||||
m1.col(1) = m2.col(2);
|
||||
m1.col(2) = m2.col(1);
|
||||
m1.col(3) = m2.col(0);
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
EIGEN_DONT_INLINE
|
||||
void bug1684_job3(MatrixType& m1, MatrixType& m2)
|
||||
{
|
||||
m2 = m1;
|
||||
Vector4f tmp;
|
||||
tmp = m2.col(0);
|
||||
m2.col(0) = m2.col(3);
|
||||
m2.col(3) = tmp;
|
||||
tmp = m2.col(1);
|
||||
m2.col(1) = m2.col(2);
|
||||
m2.col(2) = tmp;
|
||||
|
||||
}
|
||||
|
||||
template<int>
|
||||
void bug1684()
|
||||
{
|
||||
Matrix4f m1 = Matrix4f::Random();
|
||||
Matrix4f m2 = Matrix4f::Random();
|
||||
bug1684_job1(m1,m2);
|
||||
VERIFY_IS_APPROX(m2, m1.rowwise().reverse().eval());
|
||||
bug1684_job2(m1,m2);
|
||||
VERIFY_IS_APPROX(m2, m1.rowwise().reverse().eval());
|
||||
// This one still fail after our swap's workaround,
|
||||
// but I expect users not to implement their own swap.
|
||||
// bug1684_job3(m1,m2);
|
||||
// VERIFY_IS_APPROX(m2, m1.rowwise().reverse().eval());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(array_reverse)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( reverse(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( reverse(Matrix2f()) );
|
||||
CALL_SUBTEST_3( reverse(Matrix4f()) );
|
||||
CALL_SUBTEST_4( reverse(Matrix4d()) );
|
||||
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>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_3( bug1684<0>() );
|
||||
}
|
||||
CALL_SUBTEST_3( array_reverse_extra<0>() );
|
||||
}
|
||||
71
libs/eigen/test/bandmatrix.cpp
Normal file
71
libs/eigen/test/bandmatrix.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// This file is triangularView of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 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"
|
||||
|
||||
template<typename MatrixType> void bandmatrix(const MatrixType& _m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrixType;
|
||||
|
||||
Index rows = _m.rows();
|
||||
Index cols = _m.cols();
|
||||
Index supers = _m.supers();
|
||||
Index subs = _m.subs();
|
||||
|
||||
MatrixType m(rows,cols,supers,subs);
|
||||
|
||||
DenseMatrixType dm1(rows,cols);
|
||||
dm1.setZero();
|
||||
|
||||
m.diagonal().setConstant(123);
|
||||
dm1.diagonal().setConstant(123);
|
||||
for (int i=1; i<=m.supers();++i)
|
||||
{
|
||||
m.diagonal(i).setConstant(static_cast<RealScalar>(i));
|
||||
dm1.diagonal(i).setConstant(static_cast<RealScalar>(i));
|
||||
}
|
||||
for (int i=1; i<=m.subs();++i)
|
||||
{
|
||||
m.diagonal(-i).setConstant(-static_cast<RealScalar>(i));
|
||||
dm1.diagonal(-i).setConstant(-static_cast<RealScalar>(i));
|
||||
}
|
||||
//std::cerr << m.m_data << "\n\n" << m.toDense() << "\n\n" << dm1 << "\n\n\n\n";
|
||||
VERIFY_IS_APPROX(dm1,m.toDenseMatrix());
|
||||
|
||||
for (int i=0; i<cols; ++i)
|
||||
{
|
||||
m.col(i).setConstant(static_cast<RealScalar>(i+1));
|
||||
dm1.col(i).setConstant(static_cast<RealScalar>(i+1));
|
||||
}
|
||||
Index d = (std::min)(rows,cols);
|
||||
Index a = std::max<Index>(0,cols-d-supers);
|
||||
Index b = std::max<Index>(0,rows-d-subs);
|
||||
if(a>0) dm1.block(0,d+supers,rows,a).setZero();
|
||||
dm1.block(0,supers+1,cols-supers-1-a,cols-supers-1-a).template triangularView<Upper>().setZero();
|
||||
dm1.block(subs+1,0,rows-subs-1-b,rows-subs-1-b).template triangularView<Lower>().setZero();
|
||||
if(b>0) dm1.block(d+subs,0,b,cols).setZero();
|
||||
//std::cerr << m.m_data << "\n\n" << m.toDense() << "\n\n" << dm1 << "\n\n";
|
||||
VERIFY_IS_APPROX(dm1,m.toDenseMatrix());
|
||||
|
||||
}
|
||||
|
||||
using Eigen::internal::BandMatrix;
|
||||
|
||||
EIGEN_DECLARE_TEST(bandmatrix)
|
||||
{
|
||||
for(int i = 0; i < 10*g_repeat ; i++) {
|
||||
Index rows = internal::random<Index>(1,10);
|
||||
Index cols = internal::random<Index>(1,10);
|
||||
Index sups = internal::random<Index>(0,cols-1);
|
||||
Index subs = internal::random<Index>(0,rows-1);
|
||||
CALL_SUBTEST(bandmatrix(BandMatrix<float>(rows,cols,sups,subs)) );
|
||||
}
|
||||
}
|
||||
356
libs/eigen/test/basicstuff.cpp
Normal file
356
libs/eigen/test/basicstuff.cpp
Normal file
@@ -0,0 +1,356 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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 "main.h"
|
||||
#include "random_without_cast_overflow.h"
|
||||
|
||||
template<typename MatrixType> void basicStuff(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index 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);
|
||||
SquareMatrixType sm1 = SquareMatrixType::Random(rows,rows), sm2(rows,rows);
|
||||
|
||||
Scalar x = 0;
|
||||
while(x == Scalar(0)) x = internal::random<Scalar>();
|
||||
|
||||
Index r = internal::random<Index>(0, rows-1),
|
||||
c = internal::random<Index>(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]);
|
||||
|
||||
// test fetching with various index types.
|
||||
Index r1 = internal::random<Index>(0, numext::mini(Index(127),rows-1));
|
||||
x = v1(static_cast<char>(r1));
|
||||
x = v1(static_cast<signed char>(r1));
|
||||
x = v1(static_cast<unsigned char>(r1));
|
||||
x = v1(static_cast<signed short>(r1));
|
||||
x = v1(static_cast<unsigned short>(r1));
|
||||
x = v1(static_cast<signed int>(r1));
|
||||
x = v1(static_cast<unsigned int>(r1));
|
||||
x = v1(static_cast<signed long>(r1));
|
||||
x = v1(static_cast<unsigned long>(r1));
|
||||
#if EIGEN_HAS_CXX11
|
||||
x = v1(static_cast<long long int>(r1));
|
||||
x = v1(static_cast<unsigned long long int>(r1));
|
||||
#endif
|
||||
|
||||
VERIFY_IS_APPROX( v1, v1);
|
||||
VERIFY_IS_NOT_APPROX( v1, 2*v1);
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1);
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( vzero, v1.squaredNorm());
|
||||
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)));
|
||||
}
|
||||
|
||||
if(cols!=1 && rows!=1)
|
||||
{
|
||||
VERIFY_RAISES_ASSERT(m1[0]);
|
||||
VERIFY_RAISES_ASSERT((m1+m1)[0]);
|
||||
}
|
||||
|
||||
VERIFY_IS_APPROX(m3 = m1,m1);
|
||||
MatrixType m4;
|
||||
VERIFY_IS_APPROX(m4 = m1,m1);
|
||||
|
||||
m3.real() = m1.real();
|
||||
VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), static_cast<const MatrixType&>(m1).real());
|
||||
VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), m1.real());
|
||||
|
||||
// check == / != operators
|
||||
VERIFY(m1==m1);
|
||||
VERIFY(m1!=m2);
|
||||
VERIFY(!(m1==m2));
|
||||
VERIFY(!(m1!=m1));
|
||||
m1 = m2;
|
||||
VERIFY(m1==m2);
|
||||
VERIFY(!(m1!=m2));
|
||||
|
||||
// check automatic transposition
|
||||
sm2.setZero();
|
||||
for(Index i=0;i<rows;++i)
|
||||
sm2.col(i) = sm1.row(i);
|
||||
VERIFY_IS_APPROX(sm2,sm1.transpose());
|
||||
|
||||
sm2.setZero();
|
||||
for(Index i=0;i<rows;++i)
|
||||
sm2.col(i).noalias() = sm1.row(i);
|
||||
VERIFY_IS_APPROX(sm2,sm1.transpose());
|
||||
|
||||
sm2.setZero();
|
||||
for(Index i=0;i<rows;++i)
|
||||
sm2.col(i).noalias() += sm1.row(i);
|
||||
VERIFY_IS_APPROX(sm2,sm1.transpose());
|
||||
|
||||
sm2.setZero();
|
||||
for(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)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> RealMatrixType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
Scalar s1 = internal::random<Scalar>(),
|
||||
s2 = internal::random<Scalar>();
|
||||
|
||||
VERIFY(numext::real(s1)==numext::real_ref(s1));
|
||||
VERIFY(numext::imag(s1)==numext::imag_ref(s1));
|
||||
numext::real_ref(s1) = numext::real(s2);
|
||||
numext::imag_ref(s1) = numext::imag(s2);
|
||||
VERIFY(internal::isApprox(s1, s2, NumTraits<RealScalar>::epsilon()));
|
||||
// extended precision in Intel FPUs means that s1 == s2 in the line above is not guaranteed.
|
||||
|
||||
RealMatrixType rm1 = RealMatrixType::Random(rows,cols),
|
||||
rm2 = RealMatrixType::Random(rows,cols);
|
||||
MatrixType cm(rows,cols);
|
||||
cm.real() = rm1;
|
||||
cm.imag() = rm2;
|
||||
VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).real(), rm1);
|
||||
VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).imag(), rm2);
|
||||
rm1.setZero();
|
||||
rm2.setZero();
|
||||
rm1 = cm.real();
|
||||
rm2 = cm.imag();
|
||||
VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).real(), rm1);
|
||||
VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).imag(), rm2);
|
||||
cm.real().setZero();
|
||||
VERIFY(static_cast<const MatrixType&>(cm).real().isZero());
|
||||
VERIFY(!static_cast<const MatrixType&>(cm).imag().isZero());
|
||||
}
|
||||
|
||||
template<typename SrcScalar, typename TgtScalar>
|
||||
struct casting_test {
|
||||
static void run() {
|
||||
Matrix<SrcScalar,4,4> m;
|
||||
for (int i=0; i<m.rows(); ++i) {
|
||||
for (int j=0; j<m.cols(); ++j) {
|
||||
m(i, j) = internal::random_without_cast_overflow<SrcScalar,TgtScalar>::value();
|
||||
}
|
||||
}
|
||||
Matrix<TgtScalar,4,4> n = m.template cast<TgtScalar>();
|
||||
for (int i=0; i<m.rows(); ++i) {
|
||||
for (int j=0; j<m.cols(); ++j) {
|
||||
VERIFY_IS_APPROX(n(i, j), (internal::cast<SrcScalar,TgtScalar>(m(i, j))));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename SrcScalar, typename EnableIf = void>
|
||||
struct casting_test_runner {
|
||||
static void run() {
|
||||
casting_test<SrcScalar, bool>::run();
|
||||
casting_test<SrcScalar, int8_t>::run();
|
||||
casting_test<SrcScalar, uint8_t>::run();
|
||||
casting_test<SrcScalar, int16_t>::run();
|
||||
casting_test<SrcScalar, uint16_t>::run();
|
||||
casting_test<SrcScalar, int32_t>::run();
|
||||
casting_test<SrcScalar, uint32_t>::run();
|
||||
#if EIGEN_HAS_CXX11
|
||||
casting_test<SrcScalar, int64_t>::run();
|
||||
casting_test<SrcScalar, uint64_t>::run();
|
||||
#endif
|
||||
casting_test<SrcScalar, half>::run();
|
||||
casting_test<SrcScalar, bfloat16>::run();
|
||||
casting_test<SrcScalar, float>::run();
|
||||
casting_test<SrcScalar, double>::run();
|
||||
casting_test<SrcScalar, std::complex<float> >::run();
|
||||
casting_test<SrcScalar, std::complex<double> >::run();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename SrcScalar>
|
||||
struct casting_test_runner<SrcScalar, typename internal::enable_if<(NumTraits<SrcScalar>::IsComplex)>::type>
|
||||
{
|
||||
static void run() {
|
||||
// Only a few casts from std::complex<T> are defined.
|
||||
casting_test<SrcScalar, half>::run();
|
||||
casting_test<SrcScalar, bfloat16>::run();
|
||||
casting_test<SrcScalar, std::complex<float> >::run();
|
||||
casting_test<SrcScalar, std::complex<double> >::run();
|
||||
}
|
||||
};
|
||||
|
||||
void casting_all() {
|
||||
casting_test_runner<bool>::run();
|
||||
casting_test_runner<int8_t>::run();
|
||||
casting_test_runner<uint8_t>::run();
|
||||
casting_test_runner<int16_t>::run();
|
||||
casting_test_runner<uint16_t>::run();
|
||||
casting_test_runner<int32_t>::run();
|
||||
casting_test_runner<uint32_t>::run();
|
||||
#if EIGEN_HAS_CXX11
|
||||
casting_test_runner<int64_t>::run();
|
||||
casting_test_runner<uint64_t>::run();
|
||||
#endif
|
||||
casting_test_runner<half>::run();
|
||||
casting_test_runner<bfloat16>::run();
|
||||
casting_test_runner<float>::run();
|
||||
casting_test_runner<double>::run();
|
||||
casting_test_runner<std::complex<float> >::run();
|
||||
casting_test_runner<std::complex<double> >::run();
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void fixedSizeMatrixConstruction()
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(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(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_4( basicStuff(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_5( basicStuff(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( basicStuff(Matrix<float, 100, 100>()) );
|
||||
CALL_SUBTEST_7( basicStuff(Matrix<long double,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_8( casting_all() );
|
||||
|
||||
CALL_SUBTEST_3( basicStuffComplex(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_5( basicStuffComplex(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
|
||||
CALL_SUBTEST_1(fixedSizeMatrixConstruction<unsigned char>());
|
||||
CALL_SUBTEST_1(fixedSizeMatrixConstruction<float>());
|
||||
CALL_SUBTEST_1(fixedSizeMatrixConstruction<double>());
|
||||
CALL_SUBTEST_1(fixedSizeMatrixConstruction<int>());
|
||||
CALL_SUBTEST_1(fixedSizeMatrixConstruction<long int>());
|
||||
CALL_SUBTEST_1(fixedSizeMatrixConstruction<std::ptrdiff_t>());
|
||||
}
|
||||
118
libs/eigen/test/bdcsvd.cpp
Normal file
118
libs/eigen/test/bdcsvd.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
// 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;
|
||||
if(pickrandom) {
|
||||
m.resizeLike(a);
|
||||
svd_fill_random(m);
|
||||
}
|
||||
else
|
||||
m = a;
|
||||
|
||||
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);
|
||||
VERIFY_IS_APPROX(m.bdcSvd(ComputeFullU|ComputeFullV).transpose().solve(m), m);
|
||||
VERIFY_IS_APPROX(m.bdcSvd(ComputeFullU|ComputeFullV).adjoint().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());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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
|
||||
// Disabled because not supported by BDCSVD
|
||||
// CALL_SUBTEST_9( svd_preallocate<void>() );
|
||||
|
||||
CALL_SUBTEST_2( svd_underoverflow<void>() );
|
||||
}
|
||||
|
||||
378
libs/eigen/test/bfloat16_float.cpp
Normal file
378
libs/eigen/test/bfloat16_float.cpp
Normal file
@@ -0,0 +1,378 @@
|
||||
// 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 <memory>
|
||||
#include <math.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include <Eigen/src/Core/arch/Default/BFloat16.h>
|
||||
|
||||
#define VERIFY_BFLOAT16_BITS_EQUAL(h, bits) \
|
||||
VERIFY_IS_EQUAL((numext::bit_cast<numext::uint16_t>(h)), (static_cast<numext::uint16_t>(bits)))
|
||||
|
||||
// Make sure it's possible to forward declare Eigen::bfloat16
|
||||
namespace Eigen {
|
||||
struct bfloat16;
|
||||
}
|
||||
|
||||
using Eigen::bfloat16;
|
||||
|
||||
float BinaryToFloat(uint32_t sign, uint32_t exponent, uint32_t high_mantissa,
|
||||
uint32_t low_mantissa) {
|
||||
float dest;
|
||||
uint32_t src = (sign << 31) + (exponent << 23) + (high_mantissa << 16) + low_mantissa;
|
||||
memcpy(static_cast<void*>(&dest),
|
||||
static_cast<const void*>(&src), sizeof(dest));
|
||||
return dest;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void test_roundtrip() {
|
||||
// Representable T round trip via bfloat16
|
||||
VERIFY_IS_EQUAL((internal::cast<bfloat16,T>(internal::cast<T,bfloat16>(-std::numeric_limits<T>::infinity()))), -std::numeric_limits<T>::infinity());
|
||||
VERIFY_IS_EQUAL((internal::cast<bfloat16,T>(internal::cast<T,bfloat16>(std::numeric_limits<T>::infinity()))), std::numeric_limits<T>::infinity());
|
||||
VERIFY_IS_EQUAL((internal::cast<bfloat16,T>(internal::cast<T,bfloat16>(T(-1.0)))), T(-1.0));
|
||||
VERIFY_IS_EQUAL((internal::cast<bfloat16,T>(internal::cast<T,bfloat16>(T(-0.5)))), T(-0.5));
|
||||
VERIFY_IS_EQUAL((internal::cast<bfloat16,T>(internal::cast<T,bfloat16>(T(-0.0)))), T(-0.0));
|
||||
VERIFY_IS_EQUAL((internal::cast<bfloat16,T>(internal::cast<T,bfloat16>(T(1.0)))), T(1.0));
|
||||
VERIFY_IS_EQUAL((internal::cast<bfloat16,T>(internal::cast<T,bfloat16>(T(0.5)))), T(0.5));
|
||||
VERIFY_IS_EQUAL((internal::cast<bfloat16,T>(internal::cast<T,bfloat16>(T(0.0)))), T(0.0));
|
||||
}
|
||||
|
||||
void test_conversion()
|
||||
{
|
||||
using Eigen::bfloat16_impl::__bfloat16_raw;
|
||||
|
||||
// Round-trip casts
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<bfloat16>(numext::bit_cast<numext::uint16_t>(bfloat16(1.0f))),
|
||||
bfloat16(1.0f));
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<bfloat16>(numext::bit_cast<numext::uint16_t>(bfloat16(0.5f))),
|
||||
bfloat16(0.5f));
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<bfloat16>(numext::bit_cast<numext::uint16_t>(bfloat16(-0.33333f))),
|
||||
bfloat16(-0.33333f));
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<bfloat16>(numext::bit_cast<numext::uint16_t>(bfloat16(0.0f))),
|
||||
bfloat16(0.0f));
|
||||
|
||||
// Conversion from float.
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(1.0f), 0x3f80);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(0.5f), 0x3f00);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(0.33333f), 0x3eab);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(3.38e38f), 0x7f7e);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(3.40e38f), 0x7f80); // Becomes infinity.
|
||||
|
||||
// Verify round-to-nearest-even behavior.
|
||||
float val1 = static_cast<float>(bfloat16(__bfloat16_raw(0x3c00)));
|
||||
float val2 = static_cast<float>(bfloat16(__bfloat16_raw(0x3c01)));
|
||||
float val3 = static_cast<float>(bfloat16(__bfloat16_raw(0x3c02)));
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(0.5f * (val1 + val2)), 0x3c00);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(0.5f * (val2 + val3)), 0x3c02);
|
||||
|
||||
// Conversion from int.
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(-1), 0xbf80);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(0), 0x0000);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(1), 0x3f80);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(2), 0x4000);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(3), 0x4040);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(12), 0x4140);
|
||||
|
||||
// Conversion from bool.
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(false), 0x0000);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(true), 0x3f80);
|
||||
|
||||
// Conversion to bool
|
||||
VERIFY_IS_EQUAL(static_cast<bool>(bfloat16(3)), true);
|
||||
VERIFY_IS_EQUAL(static_cast<bool>(bfloat16(0.33333f)), true);
|
||||
VERIFY_IS_EQUAL(bfloat16(-0.0), false);
|
||||
VERIFY_IS_EQUAL(static_cast<bool>(bfloat16(0.0)), false);
|
||||
|
||||
// Explicit conversion to float.
|
||||
VERIFY_IS_EQUAL(static_cast<float>(bfloat16(__bfloat16_raw(0x0000))), 0.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(bfloat16(__bfloat16_raw(0x3f80))), 1.0f);
|
||||
|
||||
// Implicit conversion to float
|
||||
VERIFY_IS_EQUAL(bfloat16(__bfloat16_raw(0x0000)), 0.0f);
|
||||
VERIFY_IS_EQUAL(bfloat16(__bfloat16_raw(0x3f80)), 1.0f);
|
||||
|
||||
// Zero representations
|
||||
VERIFY_IS_EQUAL(bfloat16(0.0f), bfloat16(0.0f));
|
||||
VERIFY_IS_EQUAL(bfloat16(-0.0f), bfloat16(0.0f));
|
||||
VERIFY_IS_EQUAL(bfloat16(-0.0f), bfloat16(-0.0f));
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(0.0f), 0x0000);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(-0.0f), 0x8000);
|
||||
|
||||
// Default is zero
|
||||
VERIFY_IS_EQUAL(static_cast<float>(bfloat16()), 0.0f);
|
||||
|
||||
// Representable floats round trip via bfloat16
|
||||
test_roundtrip<float>();
|
||||
test_roundtrip<double>();
|
||||
test_roundtrip<std::complex<float> >();
|
||||
test_roundtrip<std::complex<double> >();
|
||||
|
||||
// Conversion
|
||||
Array<float,1,100> a;
|
||||
for (int i = 0; i < 100; i++) a(i) = i + 1.25;
|
||||
Array<bfloat16,1,100> b = a.cast<bfloat16>();
|
||||
Array<float,1,100> c = b.cast<float>();
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
VERIFY_LE(numext::abs(c(i) - a(i)), a(i) / 128);
|
||||
}
|
||||
|
||||
// Epsilon
|
||||
VERIFY_LE(1.0f, static_cast<float>((std::numeric_limits<bfloat16>::epsilon)() + bfloat16(1.0f)));
|
||||
VERIFY_IS_EQUAL(1.0f, static_cast<float>((std::numeric_limits<bfloat16>::epsilon)() / bfloat16(2.0f) + bfloat16(1.0f)));
|
||||
|
||||
// Negate
|
||||
VERIFY_IS_EQUAL(static_cast<float>(-bfloat16(3.0f)), -3.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(-bfloat16(-4.5f)), 4.5f);
|
||||
|
||||
|
||||
#if !EIGEN_COMP_MSVC
|
||||
// Visual Studio errors out on divisions by 0
|
||||
VERIFY((numext::isnan)(static_cast<float>(bfloat16(0.0 / 0.0))));
|
||||
VERIFY((numext::isinf)(static_cast<float>(bfloat16(1.0 / 0.0))));
|
||||
VERIFY((numext::isinf)(static_cast<float>(bfloat16(-1.0 / 0.0))));
|
||||
|
||||
// Visual Studio errors out on divisions by 0
|
||||
VERIFY((numext::isnan)(bfloat16(0.0 / 0.0)));
|
||||
VERIFY((numext::isinf)(bfloat16(1.0 / 0.0)));
|
||||
VERIFY((numext::isinf)(bfloat16(-1.0 / 0.0)));
|
||||
#endif
|
||||
|
||||
// NaNs and infinities.
|
||||
VERIFY(!(numext::isinf)(static_cast<float>(bfloat16(3.38e38f)))); // Largest finite number.
|
||||
VERIFY(!(numext::isnan)(static_cast<float>(bfloat16(0.0f))));
|
||||
VERIFY((numext::isinf)(static_cast<float>(bfloat16(__bfloat16_raw(0xff80)))));
|
||||
VERIFY((numext::isnan)(static_cast<float>(bfloat16(__bfloat16_raw(0xffc0)))));
|
||||
VERIFY((numext::isinf)(static_cast<float>(bfloat16(__bfloat16_raw(0x7f80)))));
|
||||
VERIFY((numext::isnan)(static_cast<float>(bfloat16(__bfloat16_raw(0x7fc0)))));
|
||||
|
||||
// Exactly same checks as above, just directly on the bfloat16 representation.
|
||||
VERIFY(!(numext::isinf)(bfloat16(__bfloat16_raw(0x7bff))));
|
||||
VERIFY(!(numext::isnan)(bfloat16(__bfloat16_raw(0x0000))));
|
||||
VERIFY((numext::isinf)(bfloat16(__bfloat16_raw(0xff80))));
|
||||
VERIFY((numext::isnan)(bfloat16(__bfloat16_raw(0xffc0))));
|
||||
VERIFY((numext::isinf)(bfloat16(__bfloat16_raw(0x7f80))));
|
||||
VERIFY((numext::isnan)(bfloat16(__bfloat16_raw(0x7fc0))));
|
||||
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(BinaryToFloat(0x0, 0xff, 0x40, 0x0)), 0x7fc0);
|
||||
VERIFY_BFLOAT16_BITS_EQUAL(bfloat16(BinaryToFloat(0x1, 0xff, 0x40, 0x0)), 0xffc0);
|
||||
}
|
||||
|
||||
void test_numtraits()
|
||||
{
|
||||
std::cout << "epsilon = " << NumTraits<bfloat16>::epsilon() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<bfloat16>::epsilon()) << ")" << std::endl;
|
||||
std::cout << "highest = " << NumTraits<bfloat16>::highest() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<bfloat16>::highest()) << ")" << std::endl;
|
||||
std::cout << "lowest = " << NumTraits<bfloat16>::lowest() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<bfloat16>::lowest()) << ")" << std::endl;
|
||||
std::cout << "min = " << (std::numeric_limits<bfloat16>::min)() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>((std::numeric_limits<bfloat16>::min)()) << ")" << std::endl;
|
||||
std::cout << "denorm min = " << (std::numeric_limits<bfloat16>::denorm_min)() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>((std::numeric_limits<bfloat16>::denorm_min)()) << ")" << std::endl;
|
||||
std::cout << "infinity = " << NumTraits<bfloat16>::infinity() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<bfloat16>::infinity()) << ")" << std::endl;
|
||||
std::cout << "quiet nan = " << NumTraits<bfloat16>::quiet_NaN() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<bfloat16>::quiet_NaN()) << ")" << std::endl;
|
||||
std::cout << "signaling nan = " << std::numeric_limits<bfloat16>::signaling_NaN() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(std::numeric_limits<bfloat16>::signaling_NaN()) << ")" << std::endl;
|
||||
|
||||
VERIFY(NumTraits<bfloat16>::IsSigned);
|
||||
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<numext::uint16_t>(std::numeric_limits<bfloat16>::infinity()),
|
||||
numext::bit_cast<numext::uint16_t>(bfloat16(std::numeric_limits<float>::infinity())) );
|
||||
// There is no guarantee that casting a 32-bit NaN to bfloat16 has a precise
|
||||
// bit pattern. We test that it is in fact a NaN, then test the signaling
|
||||
// bit (msb of significand is 1 for quiet, 0 for signaling).
|
||||
const numext::uint16_t BFLOAT16_QUIET_BIT = 0x0040;
|
||||
VERIFY(
|
||||
(numext::isnan)(std::numeric_limits<bfloat16>::quiet_NaN())
|
||||
&& (numext::isnan)(bfloat16(std::numeric_limits<float>::quiet_NaN()))
|
||||
&& ((numext::bit_cast<numext::uint16_t>(std::numeric_limits<bfloat16>::quiet_NaN()) & BFLOAT16_QUIET_BIT) > 0)
|
||||
&& ((numext::bit_cast<numext::uint16_t>(bfloat16(std::numeric_limits<float>::quiet_NaN())) & BFLOAT16_QUIET_BIT) > 0) );
|
||||
// After a cast to bfloat16, a signaling NaN may become non-signaling. Thus,
|
||||
// we check that both are NaN, and that only the `numeric_limits` version is
|
||||
// signaling.
|
||||
VERIFY(
|
||||
(numext::isnan)(std::numeric_limits<bfloat16>::signaling_NaN())
|
||||
&& (numext::isnan)(bfloat16(std::numeric_limits<float>::signaling_NaN()))
|
||||
&& ((numext::bit_cast<numext::uint16_t>(std::numeric_limits<bfloat16>::signaling_NaN()) & BFLOAT16_QUIET_BIT) == 0) );
|
||||
|
||||
VERIFY( (std::numeric_limits<bfloat16>::min)() > bfloat16(0.f) );
|
||||
VERIFY( (std::numeric_limits<bfloat16>::denorm_min)() > bfloat16(0.f) );
|
||||
VERIFY_IS_EQUAL( (std::numeric_limits<bfloat16>::denorm_min)()/bfloat16(2), bfloat16(0.f) );
|
||||
}
|
||||
|
||||
void test_arithmetic()
|
||||
{
|
||||
VERIFY_IS_EQUAL(static_cast<float>(bfloat16(2) + bfloat16(2)), 4);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(bfloat16(2) + bfloat16(-2)), 0);
|
||||
VERIFY_IS_APPROX(static_cast<float>(bfloat16(0.33333f) + bfloat16(0.66667f)), 1.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(bfloat16(2.0f) * bfloat16(-5.5f)), -11.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(bfloat16(1.0f) / bfloat16(3.0f)), 0.3339f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(-bfloat16(4096.0f)), -4096.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(-bfloat16(-4096.0f)), 4096.0f);
|
||||
}
|
||||
|
||||
void test_comparison()
|
||||
{
|
||||
VERIFY(bfloat16(1.0f) > bfloat16(0.5f));
|
||||
VERIFY(bfloat16(0.5f) < bfloat16(1.0f));
|
||||
VERIFY(!(bfloat16(1.0f) < bfloat16(0.5f)));
|
||||
VERIFY(!(bfloat16(0.5f) > bfloat16(1.0f)));
|
||||
|
||||
VERIFY(!(bfloat16(4.0f) > bfloat16(4.0f)));
|
||||
VERIFY(!(bfloat16(4.0f) < bfloat16(4.0f)));
|
||||
|
||||
VERIFY(!(bfloat16(0.0f) < bfloat16(-0.0f)));
|
||||
VERIFY(!(bfloat16(-0.0f) < bfloat16(0.0f)));
|
||||
VERIFY(!(bfloat16(0.0f) > bfloat16(-0.0f)));
|
||||
VERIFY(!(bfloat16(-0.0f) > bfloat16(0.0f)));
|
||||
|
||||
VERIFY(bfloat16(0.2f) > bfloat16(-1.0f));
|
||||
VERIFY(bfloat16(-1.0f) < bfloat16(0.2f));
|
||||
VERIFY(bfloat16(-16.0f) < bfloat16(-15.0f));
|
||||
|
||||
VERIFY(bfloat16(1.0f) == bfloat16(1.0f));
|
||||
VERIFY(bfloat16(1.0f) != bfloat16(2.0f));
|
||||
|
||||
// Comparisons with NaNs and infinities.
|
||||
#if !EIGEN_COMP_MSVC
|
||||
// Visual Studio errors out on divisions by 0
|
||||
VERIFY(!(bfloat16(0.0 / 0.0) == bfloat16(0.0 / 0.0)));
|
||||
VERIFY(bfloat16(0.0 / 0.0) != bfloat16(0.0 / 0.0));
|
||||
|
||||
VERIFY(!(bfloat16(1.0) == bfloat16(0.0 / 0.0)));
|
||||
VERIFY(!(bfloat16(1.0) < bfloat16(0.0 / 0.0)));
|
||||
VERIFY(!(bfloat16(1.0) > bfloat16(0.0 / 0.0)));
|
||||
VERIFY(bfloat16(1.0) != bfloat16(0.0 / 0.0));
|
||||
|
||||
VERIFY(bfloat16(1.0) < bfloat16(1.0 / 0.0));
|
||||
VERIFY(bfloat16(1.0) > bfloat16(-1.0 / 0.0));
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_basic_functions()
|
||||
{
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::abs(bfloat16(3.5f))), 3.5f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(abs(bfloat16(3.5f))), 3.5f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::abs(bfloat16(-3.5f))), 3.5f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(abs(bfloat16(-3.5f))), 3.5f);
|
||||
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::floor(bfloat16(3.5f))), 3.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(floor(bfloat16(3.5f))), 3.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::floor(bfloat16(-3.5f))), -4.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(floor(bfloat16(-3.5f))), -4.0f);
|
||||
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::ceil(bfloat16(3.5f))), 4.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(ceil(bfloat16(3.5f))), 4.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::ceil(bfloat16(-3.5f))), -3.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(ceil(bfloat16(-3.5f))), -3.0f);
|
||||
|
||||
VERIFY_IS_APPROX(static_cast<float>(numext::sqrt(bfloat16(0.0f))), 0.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(sqrt(bfloat16(0.0f))), 0.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(numext::sqrt(bfloat16(4.0f))), 2.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(sqrt(bfloat16(4.0f))), 2.0f);
|
||||
|
||||
VERIFY_IS_APPROX(static_cast<float>(numext::pow(bfloat16(0.0f), bfloat16(1.0f))), 0.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(pow(bfloat16(0.0f), bfloat16(1.0f))), 0.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(numext::pow(bfloat16(2.0f), bfloat16(2.0f))), 4.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(pow(bfloat16(2.0f), bfloat16(2.0f))), 4.0f);
|
||||
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::exp(bfloat16(0.0f))), 1.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(exp(bfloat16(0.0f))), 1.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(numext::exp(bfloat16(EIGEN_PI))), 20.f + static_cast<float>(EIGEN_PI));
|
||||
VERIFY_IS_APPROX(static_cast<float>(exp(bfloat16(EIGEN_PI))), 20.f + static_cast<float>(EIGEN_PI));
|
||||
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::expm1(bfloat16(0.0f))), 0.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(expm1(bfloat16(0.0f))), 0.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(numext::expm1(bfloat16(2.0f))), 6.375f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(expm1(bfloat16(2.0f))), 6.375f);
|
||||
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::log(bfloat16(1.0f))), 0.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(log(bfloat16(1.0f))), 0.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(numext::log(bfloat16(10.0f))), 2.296875f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(log(bfloat16(10.0f))), 2.296875f);
|
||||
|
||||
VERIFY_IS_EQUAL(static_cast<float>(numext::log1p(bfloat16(0.0f))), 0.0f);
|
||||
VERIFY_IS_EQUAL(static_cast<float>(log1p(bfloat16(0.0f))), 0.0f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(numext::log1p(bfloat16(10.0f))), 2.390625f);
|
||||
VERIFY_IS_APPROX(static_cast<float>(log1p(bfloat16(10.0f))), 2.390625f);
|
||||
}
|
||||
|
||||
void test_trigonometric_functions()
|
||||
{
|
||||
VERIFY_IS_APPROX(numext::cos(bfloat16(0.0f)), bfloat16(cosf(0.0f)));
|
||||
VERIFY_IS_APPROX(cos(bfloat16(0.0f)), bfloat16(cosf(0.0f)));
|
||||
VERIFY_IS_APPROX(numext::cos(bfloat16(EIGEN_PI)), bfloat16(cosf(EIGEN_PI)));
|
||||
// VERIFY_IS_APPROX(numext::cos(bfloat16(EIGEN_PI/2)), bfloat16(cosf(EIGEN_PI/2)));
|
||||
// VERIFY_IS_APPROX(numext::cos(bfloat16(3*EIGEN_PI/2)), bfloat16(cosf(3*EIGEN_PI/2)));
|
||||
VERIFY_IS_APPROX(numext::cos(bfloat16(3.5f)), bfloat16(cosf(3.5f)));
|
||||
|
||||
VERIFY_IS_APPROX(numext::sin(bfloat16(0.0f)), bfloat16(sinf(0.0f)));
|
||||
VERIFY_IS_APPROX(sin(bfloat16(0.0f)), bfloat16(sinf(0.0f)));
|
||||
// VERIFY_IS_APPROX(numext::sin(bfloat16(EIGEN_PI)), bfloat16(sinf(EIGEN_PI)));
|
||||
VERIFY_IS_APPROX(numext::sin(bfloat16(EIGEN_PI/2)), bfloat16(sinf(EIGEN_PI/2)));
|
||||
VERIFY_IS_APPROX(numext::sin(bfloat16(3*EIGEN_PI/2)), bfloat16(sinf(3*EIGEN_PI/2)));
|
||||
VERIFY_IS_APPROX(numext::sin(bfloat16(3.5f)), bfloat16(sinf(3.5f)));
|
||||
|
||||
VERIFY_IS_APPROX(numext::tan(bfloat16(0.0f)), bfloat16(tanf(0.0f)));
|
||||
VERIFY_IS_APPROX(tan(bfloat16(0.0f)), bfloat16(tanf(0.0f)));
|
||||
// VERIFY_IS_APPROX(numext::tan(bfloat16(EIGEN_PI)), bfloat16(tanf(EIGEN_PI)));
|
||||
// VERIFY_IS_APPROX(numext::tan(bfloat16(EIGEN_PI/2)), bfloat16(tanf(EIGEN_PI/2)));
|
||||
// VERIFY_IS_APPROX(numext::tan(bfloat16(3*EIGEN_PI/2)), bfloat16(tanf(3*EIGEN_PI/2)));
|
||||
VERIFY_IS_APPROX(numext::tan(bfloat16(3.5f)), bfloat16(tanf(3.5f)));
|
||||
}
|
||||
|
||||
void test_array()
|
||||
{
|
||||
typedef Array<bfloat16,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, bfloat16(2)*a1 );
|
||||
VERIFY( (a1.abs() >= bfloat16(0)).all() );
|
||||
VERIFY_IS_APPROX( (a1*a1).sqrt(), a1.abs() );
|
||||
|
||||
VERIFY( ((a1.min)(a2) <= (a1.max)(a2)).all() );
|
||||
a1(i) = bfloat16(-10.);
|
||||
VERIFY_IS_EQUAL( a1.minCoeff(), bfloat16(-10.) );
|
||||
a1(i) = bfloat16(10.);
|
||||
VERIFY_IS_EQUAL( a1.maxCoeff(), bfloat16(10.) );
|
||||
|
||||
std::stringstream ss;
|
||||
ss << a1;
|
||||
}
|
||||
|
||||
void test_product()
|
||||
{
|
||||
typedef Matrix<bfloat16,Dynamic,Dynamic> MatrixXh;
|
||||
Index rows = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
Index cols = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
Index depth = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
MatrixXh Ah = MatrixXh::Random(rows,depth);
|
||||
MatrixXh Bh = MatrixXh::Random(depth,cols);
|
||||
MatrixXh Ch = MatrixXh::Random(rows,cols);
|
||||
MatrixXf Af = Ah.cast<float>();
|
||||
MatrixXf Bf = Bh.cast<float>();
|
||||
MatrixXf Cf = Ch.cast<float>();
|
||||
VERIFY_IS_APPROX(Ch.noalias()+=Ah*Bh, (Cf.noalias()+=Af*Bf).cast<bfloat16>());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(bfloat16_float)
|
||||
{
|
||||
CALL_SUBTEST(test_numtraits());
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST(test_conversion());
|
||||
CALL_SUBTEST(test_arithmetic());
|
||||
CALL_SUBTEST(test_comparison());
|
||||
CALL_SUBTEST(test_basic_functions());
|
||||
CALL_SUBTEST(test_trigonometric_functions());
|
||||
CALL_SUBTEST(test_array());
|
||||
CALL_SUBTEST(test_product());
|
||||
}
|
||||
}
|
||||
34
libs/eigen/test/bicgstab.cpp
Normal file
34
libs/eigen/test/bicgstab.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// 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, typename I_> void test_bicgstab_T()
|
||||
{
|
||||
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) );
|
||||
//CALL_SUBTEST( check_sparse_square_solving(bicgstab_colmajor_ssor) );
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(bicgstab)
|
||||
{
|
||||
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>()));
|
||||
}
|
||||
210
libs/eigen/test/blasutil.cpp
Normal file
210
libs/eigen/test/blasutil.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2020 Everton Constantino <everton.constantino@ibm.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"
|
||||
|
||||
// Disable "ignoring attributes on template argument"
|
||||
// for packet_traits<Packet*>
|
||||
// => The only workaround would be to wrap _m128 and the likes
|
||||
// within wrappers.
|
||||
#if EIGEN_GNUC_AT_LEAST(6,0)
|
||||
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||
#endif
|
||||
|
||||
#define GET(i,j) (StorageOrder == RowMajor ? (i)*stride + (j) : (i) + (j)*stride)
|
||||
#define SCATTER(i,j,k) (StorageOrder == RowMajor ? ((i)+(k))*stride + (j) : (i) + ((j)+(k))*stride)
|
||||
|
||||
template<typename Scalar, typename Packet>
|
||||
void compare(const Packet& a, const Packet& b)
|
||||
{
|
||||
int pktsz = internal::packet_traits<Scalar>::size;
|
||||
Scalar *buffA = new Scalar[pktsz];
|
||||
Scalar *buffB = new Scalar[pktsz];
|
||||
|
||||
internal::pstoreu<Scalar, Packet>(buffA, a);
|
||||
internal::pstoreu<Scalar, Packet>(buffB, b);
|
||||
|
||||
for(int i = 0; i < pktsz; i++)
|
||||
{
|
||||
VERIFY_IS_EQUAL(buffA[i], buffB[i]);
|
||||
}
|
||||
|
||||
delete[] buffA;
|
||||
delete[] buffB;
|
||||
}
|
||||
|
||||
template<typename Scalar, int StorageOrder, int n>
|
||||
struct PacketBlockSet
|
||||
{
|
||||
typedef typename internal::packet_traits<Scalar>::type Packet;
|
||||
|
||||
void setPacketBlock(internal::PacketBlock<Packet,n>& block, Scalar value)
|
||||
{
|
||||
for(int idx = 0; idx < n; idx++)
|
||||
{
|
||||
block.packet[idx] = internal::pset1<Packet>(value);
|
||||
}
|
||||
}
|
||||
|
||||
void comparePacketBlock(Scalar *data, int i, int j, int stride, internal::PacketBlock<Packet, n>& block)
|
||||
{
|
||||
for(int idx = 0; idx < n; idx++)
|
||||
{
|
||||
Packet line = internal::ploadu<Packet>(data + SCATTER(i,j,idx));
|
||||
compare<Scalar, Packet>(block.packet[idx], line);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, int StorageOrder, int BlockSize>
|
||||
void run_bdmp_spec_1()
|
||||
{
|
||||
typedef internal::blas_data_mapper<Scalar, int, StorageOrder> BlasDataMapper;
|
||||
int packetSize = internal::packet_traits<Scalar>::size;
|
||||
int minSize = std::max<int>(packetSize, BlockSize);
|
||||
typedef typename internal::packet_traits<Scalar>::type Packet;
|
||||
|
||||
int szm = internal::random<int>(minSize,500), szn = internal::random<int>(minSize,500);
|
||||
int stride = StorageOrder == RowMajor ? szn : szm;
|
||||
Scalar *d = new Scalar[szn*szm];
|
||||
|
||||
// Initializing with random entries
|
||||
for(int i = 0; i < szm*szn; i++)
|
||||
{
|
||||
d[i] = internal::random<Scalar>(static_cast<Scalar>(3), static_cast<Scalar>(10));
|
||||
}
|
||||
|
||||
BlasDataMapper bdm(d, stride);
|
||||
|
||||
// Testing operator()
|
||||
for(int i = 0; i < szm; i++)
|
||||
{
|
||||
for(int j = 0; j < szn; j++)
|
||||
{
|
||||
VERIFY_IS_EQUAL(d[GET(i,j)], bdm(i,j));
|
||||
}
|
||||
}
|
||||
|
||||
// Testing getSubMapper and getLinearMapper
|
||||
int i0 = internal::random<int>(0,szm-2);
|
||||
int j0 = internal::random<int>(0,szn-2);
|
||||
for(int i = i0; i < szm; i++)
|
||||
{
|
||||
for(int j = j0; j < szn; j++)
|
||||
{
|
||||
const BlasDataMapper& bdmSM = bdm.getSubMapper(i0,j0);
|
||||
const internal::BlasLinearMapper<Scalar, int, 0>& bdmLM = bdm.getLinearMapper(i0,j0);
|
||||
|
||||
Scalar v = bdmSM(i - i0, j - j0);
|
||||
Scalar vd = d[GET(i,j)];
|
||||
VERIFY_IS_EQUAL(vd, v);
|
||||
VERIFY_IS_EQUAL(vd, bdmLM(GET(i-i0, j-j0)));
|
||||
}
|
||||
}
|
||||
|
||||
// Testing loadPacket
|
||||
for(int i = 0; i < szm - minSize; i++)
|
||||
{
|
||||
for(int j = 0; j < szn - minSize; j++)
|
||||
{
|
||||
Packet pktBDM = bdm.template loadPacket<Packet>(i,j);
|
||||
Packet pktD = internal::ploadu<Packet>(d + GET(i,j));
|
||||
|
||||
compare<Scalar, Packet>(pktBDM, pktD);
|
||||
}
|
||||
}
|
||||
|
||||
// Testing gatherPacket
|
||||
Scalar *buff = new Scalar[packetSize];
|
||||
for(int i = 0; i < szm - minSize; i++)
|
||||
{
|
||||
for(int j = 0; j < szn - minSize; j++)
|
||||
{
|
||||
Packet p = bdm.template gatherPacket<Packet>(i,j);
|
||||
internal::pstoreu<Scalar, Packet>(buff, p);
|
||||
|
||||
for(int k = 0; k < packetSize; k++)
|
||||
{
|
||||
VERIFY_IS_EQUAL(d[SCATTER(i,j,k)], buff[k]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
delete[] buff;
|
||||
|
||||
// Testing scatterPacket
|
||||
for(int i = 0; i < szm - minSize; i++)
|
||||
{
|
||||
for(int j = 0; j < szn - minSize; j++)
|
||||
{
|
||||
Packet p = internal::pset1<Packet>(static_cast<Scalar>(1));
|
||||
bdm.template scatterPacket<Packet>(i,j,p);
|
||||
for(int k = 0; k < packetSize; k++)
|
||||
{
|
||||
VERIFY_IS_EQUAL(d[SCATTER(i,j,k)], static_cast<Scalar>(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Testing storePacketBlock
|
||||
internal::PacketBlock<Packet, BlockSize> block;
|
||||
|
||||
PacketBlockSet<Scalar, StorageOrder, BlockSize> pbs;
|
||||
pbs.setPacketBlock(block, static_cast<Scalar>(2));
|
||||
|
||||
for(int i = 0; i < szm - minSize; i++)
|
||||
{
|
||||
for(int j = 0; j < szn - minSize; j++)
|
||||
{
|
||||
bdm.template storePacketBlock<Packet, BlockSize>(i, j, block);
|
||||
|
||||
pbs.comparePacketBlock(d, i, j, stride, block);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] d;
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
void run_test()
|
||||
{
|
||||
run_bdmp_spec_1<Scalar, RowMajor, 1>();
|
||||
run_bdmp_spec_1<Scalar, ColMajor, 1>();
|
||||
run_bdmp_spec_1<Scalar, RowMajor, 2>();
|
||||
run_bdmp_spec_1<Scalar, ColMajor, 2>();
|
||||
run_bdmp_spec_1<Scalar, RowMajor, 4>();
|
||||
run_bdmp_spec_1<Scalar, ColMajor, 4>();
|
||||
run_bdmp_spec_1<Scalar, RowMajor, 8>();
|
||||
run_bdmp_spec_1<Scalar, ColMajor, 8>();
|
||||
run_bdmp_spec_1<Scalar, RowMajor, 16>();
|
||||
run_bdmp_spec_1<Scalar, ColMajor, 16>();
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(blasutil)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++)
|
||||
{
|
||||
CALL_SUBTEST_1(run_test<numext::int8_t>());
|
||||
CALL_SUBTEST_2(run_test<numext::int16_t>());
|
||||
CALL_SUBTEST_3(run_test<numext::int32_t>());
|
||||
|
||||
// TODO: Replace this by a call to numext::int64_t as soon as we have a way to
|
||||
// detect the typedef for int64_t on all platforms
|
||||
#if EIGEN_HAS_CXX11
|
||||
CALL_SUBTEST_4(run_test<signed long long>());
|
||||
#else
|
||||
CALL_SUBTEST_4(run_test<signed long>());
|
||||
#endif
|
||||
|
||||
CALL_SUBTEST_5(run_test<float_t>());
|
||||
CALL_SUBTEST_6(run_test<double_t>());
|
||||
CALL_SUBTEST_7(run_test<std::complex<float> >());
|
||||
CALL_SUBTEST_8(run_test<std::complex<double> >());
|
||||
}
|
||||
}
|
||||
316
libs/eigen/test/block.cpp
Normal file
316
libs/eigen/test/block.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-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/.
|
||||
|
||||
#define EIGEN_NO_STATIC_ASSERT // otherwise we fail at compile time on unused paths
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType, typename Index, typename Scalar>
|
||||
typename Eigen::internal::enable_if<!NumTraits<typename MatrixType::Scalar>::IsComplex,typename MatrixType::Scalar>::type
|
||||
block_real_only(const MatrixType &m1, Index r1, Index r2, Index c1, Index c2, const Scalar& s1) {
|
||||
// check cwise-Functions:
|
||||
VERIFY_IS_APPROX(m1.row(r1).cwiseMax(s1), m1.cwiseMax(s1).row(r1));
|
||||
VERIFY_IS_APPROX(m1.col(c1).cwiseMin(s1), m1.cwiseMin(s1).col(c1));
|
||||
|
||||
VERIFY_IS_APPROX(m1.block(r1,c1,r2-r1+1,c2-c1+1).cwiseMin(s1), m1.cwiseMin(s1).block(r1,c1,r2-r1+1,c2-c1+1));
|
||||
VERIFY_IS_APPROX(m1.block(r1,c1,r2-r1+1,c2-c1+1).cwiseMax(s1), m1.cwiseMax(s1).block(r1,c1,r2-r1+1,c2-c1+1));
|
||||
|
||||
return Scalar(0);
|
||||
}
|
||||
|
||||
template<typename MatrixType, typename Index, typename Scalar>
|
||||
typename Eigen::internal::enable_if<NumTraits<typename MatrixType::Scalar>::IsComplex,typename MatrixType::Scalar>::type
|
||||
block_real_only(const MatrixType &, Index, Index, Index, Index, const Scalar&) {
|
||||
return Scalar(0);
|
||||
}
|
||||
|
||||
// Check at compile-time that T1==T2, and at runtime-time that a==b
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_block(const T1& a, const T2& b)
|
||||
{
|
||||
return a.isApprox(b);
|
||||
}
|
||||
|
||||
template<typename MatrixType> void block(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic, MatrixType::IsRowMajor?RowMajor:ColMajor> DynamicMatrixType;
|
||||
typedef Matrix<Scalar, Dynamic, 1> DynamicVectorType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m1_copy = m1,
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
ones = MatrixType::Ones(rows, cols);
|
||||
VectorType v1 = VectorType::Random(rows);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
|
||||
Index r1 = internal::random<Index>(0,rows-1);
|
||||
Index r2 = internal::random<Index>(r1,rows-1);
|
||||
Index c1 = internal::random<Index>(0,cols-1);
|
||||
Index c2 = internal::random<Index>(c1,cols-1);
|
||||
|
||||
block_real_only(m1, r1, r2, c1, c1, s1);
|
||||
|
||||
//check row() and col()
|
||||
VERIFY_IS_EQUAL(m1.col(c1).transpose(), m1.transpose().row(c1));
|
||||
//check operator(), both constant and non-constant, on row() and col()
|
||||
m1 = m1_copy;
|
||||
m1.row(r1) += s1 * m1_copy.row(r2);
|
||||
VERIFY_IS_APPROX(m1.row(r1), m1_copy.row(r1) + s1 * m1_copy.row(r2));
|
||||
// check nested block xpr on lhs
|
||||
m1.row(r1).row(0) += s1 * m1_copy.row(r2);
|
||||
VERIFY_IS_APPROX(m1.row(r1), m1_copy.row(r1) + Scalar(2) * s1 * m1_copy.row(r2));
|
||||
m1 = m1_copy;
|
||||
m1.col(c1) += s1 * m1_copy.col(c2);
|
||||
VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + s1 * m1_copy.col(c2));
|
||||
m1.col(c1).col(0) += s1 * m1_copy.col(c2);
|
||||
VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + Scalar(2) * s1 * m1_copy.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_EQUAL(b1, m1.block(r1,c1,1,1));
|
||||
VERIFY_IS_EQUAL(m1.row(r1), br1);
|
||||
VERIFY_IS_EQUAL(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);
|
||||
|
||||
const Index BlockRows = 2;
|
||||
const Index BlockCols = 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_EQUAL(b, m1.block(3,3,BlockRows,BlockCols));
|
||||
|
||||
// same tests with mixed fixed/dynamic size
|
||||
m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols) *= s1;
|
||||
m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols)(0,3) = m1.template block<2,5>(1,1)(1,2);
|
||||
Matrix<Scalar,Dynamic,Dynamic> b2 = m1.template block<Dynamic,BlockCols>(3,3,2,5);
|
||||
VERIFY_IS_EQUAL(b2, m1.block(3,3,BlockRows,BlockCols));
|
||||
|
||||
VERIFY(is_same_block(m1.block(3,3,BlockRows,BlockCols), m1.block(3,3,fix<Dynamic>(BlockRows),fix<Dynamic>(BlockCols))));
|
||||
VERIFY(is_same_block(m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols), m1.block(1,1,fix<BlockRows>,BlockCols)));
|
||||
VERIFY(is_same_block(m1.template block<BlockRows,BlockCols>(1,1,BlockRows,BlockCols), m1.block(1,1,fix<BlockRows>(),fix<BlockCols>)));
|
||||
VERIFY(is_same_block(m1.template block<BlockRows,BlockCols>(1,1,BlockRows,BlockCols), m1.block(1,1,fix<BlockRows>,fix<BlockCols>(BlockCols))));
|
||||
}
|
||||
|
||||
if (rows>2)
|
||||
{
|
||||
// test sub vectors
|
||||
VERIFY_IS_EQUAL(v1.template head<2>(), v1.block(0,0,2,1));
|
||||
VERIFY_IS_EQUAL(v1.template head<2>(), v1.head(2));
|
||||
VERIFY_IS_EQUAL(v1.template head<2>(), v1.segment(0,2));
|
||||
VERIFY_IS_EQUAL(v1.template head<2>(), v1.template segment<2>(0));
|
||||
Index i = rows-2;
|
||||
VERIFY_IS_EQUAL(v1.template tail<2>(), v1.block(i,0,2,1));
|
||||
VERIFY_IS_EQUAL(v1.template tail<2>(), v1.tail(2));
|
||||
VERIFY_IS_EQUAL(v1.template tail<2>(), v1.segment(i,2));
|
||||
VERIFY_IS_EQUAL(v1.template tail<2>(), v1.template segment<2>(i));
|
||||
i = internal::random<Index>(0,rows-2);
|
||||
VERIFY_IS_EQUAL(v1.segment(i,2), v1.template segment<2>(i));
|
||||
}
|
||||
|
||||
// stress some basic stuffs with block matrices
|
||||
VERIFY(numext::real(ones.col(c1).sum()) == RealScalar(rows));
|
||||
VERIFY(numext::real(ones.row(r1).sum()) == RealScalar(cols));
|
||||
|
||||
VERIFY(numext::real(ones.col(c1).dot(ones.col(c2))) == RealScalar(rows));
|
||||
VERIFY(numext::real(ones.row(r1).dot(ones.row(r2))) == RealScalar(cols));
|
||||
|
||||
// check 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.
|
||||
|
||||
// expressions with direct access
|
||||
VERIFY_IS_EQUAL( (m1.block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , (m1.block(r2,c2,rows-r2,cols-c2)) );
|
||||
VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , (m1.row(r1).segment(c1,c2-c1+1)) );
|
||||
VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , (m1.col(c1).segment(r1,r2-r1+1)) );
|
||||
VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , (m1.row(r1).segment(c1,c2-c1+1)).transpose() );
|
||||
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_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).row(0)) , ((m1+m2).eval().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() );
|
||||
VERIFY_IS_APPROX( ((m1+m2).template block<Dynamic,1>(r1,c1,r2-r1+1,1)) , ((m1+m2).eval().col(c1).eval().segment(r1,r2-r1+1)) );
|
||||
VERIFY_IS_APPROX( ((m1+m2).template block<1,Dynamic>(r1,c1,1,c2-c1+1)) , ((m1+m2).eval().row(r1).eval().segment(c1,c2-c1+1)) );
|
||||
VERIFY_IS_APPROX( ((m1+m2).transpose().template block<1,Dynamic>(c1,r1,1,r2-r1+1)) , ((m1+m2).eval().col(c1).eval().segment(r1,r2-r1+1)).transpose() );
|
||||
VERIFY_IS_APPROX( (m1+m2).row(r1).eval(), (m1+m2).eval().row(r1) );
|
||||
VERIFY_IS_APPROX( (m1+m2).adjoint().col(r1).eval(), (m1+m2).adjoint().eval().col(r1) );
|
||||
VERIFY_IS_APPROX( (m1+m2).adjoint().row(c1).eval(), (m1+m2).adjoint().eval().row(c1) );
|
||||
VERIFY_IS_APPROX( (m1*1).row(r1).segment(c1,c2-c1+1).eval(), m1.row(r1).eval().segment(c1,c2-c1+1).eval() );
|
||||
VERIFY_IS_APPROX( m1.col(c1).reverse().segment(r1,r2-r1+1).eval(),m1.col(c1).reverse().eval().segment(r1,r2-r1+1).eval() );
|
||||
|
||||
VERIFY_IS_APPROX( (m1*1).topRows(r1), m1.topRows(r1) );
|
||||
VERIFY_IS_APPROX( (m1*1).leftCols(c1), m1.leftCols(c1) );
|
||||
VERIFY_IS_APPROX( (m1*1).transpose().topRows(c1), m1.transpose().topRows(c1) );
|
||||
VERIFY_IS_APPROX( (m1*1).transpose().leftCols(r1), m1.transpose().leftCols(r1) );
|
||||
VERIFY_IS_APPROX( (m1*1).transpose().middleRows(c1,c2-c1+1), m1.transpose().middleRows(c1,c2-c1+1) );
|
||||
VERIFY_IS_APPROX( (m1*1).transpose().middleCols(r1,r2-r1+1), m1.transpose().middleCols(r1,r2-r1+1) );
|
||||
|
||||
// evaluation into plain matrices from expressions with direct access (stress MapBase)
|
||||
DynamicMatrixType dm;
|
||||
DynamicVectorType dv;
|
||||
dm.setZero();
|
||||
dm = m1.block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2);
|
||||
VERIFY_IS_EQUAL(dm, (m1.block(r2,c2,rows-r2,cols-c2)));
|
||||
dm.setZero();
|
||||
dv.setZero();
|
||||
dm = m1.block(r1,c1,r2-r1+1,c2-c1+1).row(0).transpose();
|
||||
dv = m1.row(r1).segment(c1,c2-c1+1);
|
||||
VERIFY_IS_EQUAL(dv, dm);
|
||||
dm.setZero();
|
||||
dv.setZero();
|
||||
dm = m1.col(c1).segment(r1,r2-r1+1);
|
||||
dv = m1.block(r1,c1,r2-r1+1,c2-c1+1).col(0);
|
||||
VERIFY_IS_EQUAL(dv, dm);
|
||||
dm.setZero();
|
||||
dv.setZero();
|
||||
dm = m1.block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0);
|
||||
dv = m1.row(r1).segment(c1,c2-c1+1);
|
||||
VERIFY_IS_EQUAL(dv, dm);
|
||||
dm.setZero();
|
||||
dv.setZero();
|
||||
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() );
|
||||
}
|
||||
|
||||
VERIFY_IS_EQUAL( m1.template subVector<Horizontal>(r1), m1.row(r1) );
|
||||
VERIFY_IS_APPROX( (m1+m1).template subVector<Horizontal>(r1), (m1+m1).row(r1) );
|
||||
VERIFY_IS_EQUAL( m1.template subVector<Vertical>(c1), m1.col(c1) );
|
||||
VERIFY_IS_APPROX( (m1+m1).template subVector<Vertical>(c1), (m1+m1).col(c1) );
|
||||
VERIFY_IS_EQUAL( m1.template subVectors<Horizontal>(), m1.rows() );
|
||||
VERIFY_IS_EQUAL( m1.template subVectors<Vertical>(), m1.cols() );
|
||||
|
||||
if (rows>=2 || cols>=2) {
|
||||
VERIFY_IS_EQUAL( int(m1.middleCols(0,0).IsRowMajor), int(m1.IsRowMajor) );
|
||||
VERIFY_IS_EQUAL( m1.middleCols(0,0).outerSize(), m1.IsRowMajor ? rows : 0);
|
||||
VERIFY_IS_EQUAL( m1.middleCols(0,0).innerSize(), m1.IsRowMajor ? 0 : rows);
|
||||
|
||||
VERIFY_IS_EQUAL( int(m1.middleRows(0,0).IsRowMajor), int(m1.IsRowMajor) );
|
||||
VERIFY_IS_EQUAL( m1.middleRows(0,0).outerSize(), m1.IsRowMajor ? 0 : cols);
|
||||
VERIFY_IS_EQUAL( m1.middleRows(0,0).innerSize(), m1.IsRowMajor ? cols : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename MatrixType>
|
||||
void compare_using_data_and_stride(const MatrixType& m)
|
||||
{
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
Index size = m.size();
|
||||
Index innerStride = m.innerStride();
|
||||
Index outerStride = m.outerStride();
|
||||
Index rowStride = m.rowStride();
|
||||
Index colStride = m.colStride();
|
||||
const typename MatrixType::Scalar* data = m.data();
|
||||
|
||||
for(int j=0;j<cols;++j)
|
||||
for(int i=0;i<rows;++i)
|
||||
VERIFY(m.coeff(i,j) == data[i*rowStride + j*colStride]);
|
||||
|
||||
if(!MatrixType::IsVectorAtCompileTime)
|
||||
{
|
||||
for(int j=0;j<cols;++j)
|
||||
for(int i=0;i<rows;++i)
|
||||
VERIFY(m.coeff(i,j) == data[(MatrixType::Flags&RowMajorBit)
|
||||
? i*outerStride + j*innerStride
|
||||
: j*outerStride + i*innerStride]);
|
||||
}
|
||||
|
||||
if(MatrixType::IsVectorAtCompileTime)
|
||||
{
|
||||
VERIFY(innerStride == int((&m.coeff(1))-(&m.coeff(0))));
|
||||
for (int i=0;i<size;++i)
|
||||
VERIFY(m.coeff(i) == data[i*innerStride]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
void data_and_stride(const MatrixType& m)
|
||||
{
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
Index r1 = internal::random<Index>(0,rows-1);
|
||||
Index r2 = internal::random<Index>(r1,rows-1);
|
||||
Index c1 = internal::random<Index>(0,cols-1);
|
||||
Index c2 = internal::random<Index>(c1,cols-1);
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols);
|
||||
compare_using_data_and_stride(m1.block(r1, c1, r2-r1+1, c2-c1+1));
|
||||
compare_using_data_and_stride(m1.transpose().block(c1, r1, c2-c1+1, r2-r1+1));
|
||||
compare_using_data_and_stride(m1.row(r1));
|
||||
compare_using_data_and_stride(m1.col(c1));
|
||||
compare_using_data_and_stride(m1.row(r1).transpose());
|
||||
compare_using_data_and_stride(m1.col(c1).transpose());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(block)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( block(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_1( block(Matrix<float, 1, Dynamic>(internal::random(2,50))) );
|
||||
CALL_SUBTEST_1( block(Matrix<float, Dynamic, 1>(internal::random(2,50))) );
|
||||
CALL_SUBTEST_2( block(Matrix4d()) );
|
||||
CALL_SUBTEST_3( block(MatrixXcf(internal::random(2,50), internal::random(2,50))) );
|
||||
CALL_SUBTEST_4( block(MatrixXi(internal::random(2,50), internal::random(2,50))) );
|
||||
CALL_SUBTEST_5( block(MatrixXcd(internal::random(2,50), internal::random(2,50))) );
|
||||
CALL_SUBTEST_6( block(MatrixXf(internal::random(2,50), internal::random(2,50))) );
|
||||
CALL_SUBTEST_7( block(Matrix<int,Dynamic,Dynamic,RowMajor>(internal::random(2,50), internal::random(2,50))) );
|
||||
|
||||
CALL_SUBTEST_8( block(Matrix<float,Dynamic,4>(3, 4)) );
|
||||
|
||||
#ifndef EIGEN_DEFAULT_TO_ROW_MAJOR
|
||||
CALL_SUBTEST_6( data_and_stride(MatrixXf(internal::random(5,50), internal::random(5,50))) );
|
||||
CALL_SUBTEST_7( data_and_stride(Matrix<int,Dynamic,Dynamic,RowMajor>(internal::random(5,50), internal::random(5,50))) );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
208
libs/eigen/test/boostmultiprec.cpp
Normal file
208
libs/eigen/test/boostmultiprec.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
// 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
|
||||
|
||||
#ifdef EIGEN_TEST_PART_11
|
||||
#include "simplicial_cholesky.cpp"
|
||||
#endif
|
||||
|
||||
#include <Eigen/Dense>
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
#undef isnan
|
||||
#undef isinf
|
||||
#undef isfinite
|
||||
#undef I
|
||||
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#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 {
|
||||
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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;
|
||||
|
||||
// check 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))) ));
|
||||
|
||||
CALL_SUBTEST_11(( test_simplicial_cholesky_T<Real,int,ColMajor>() ));
|
||||
}
|
||||
13
libs/eigen/test/bug1213.cpp
Normal file
13
libs/eigen/test/bug1213.cpp
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
8
libs/eigen/test/bug1213.h
Normal file
8
libs/eigen/test/bug1213.h
Normal file
@@ -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);
|
||||
|
||||
18
libs/eigen/test/bug1213_main.cpp
Normal file
18
libs/eigen/test/bug1213_main.cpp
Normal file
@@ -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&);
|
||||
532
libs/eigen/test/cholesky.cpp
Normal file
532
libs/eigen/test/cholesky.cpp
Normal file
@@ -0,0 +1,532 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 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"
|
||||
#include <Eigen/Cholesky>
|
||||
#include <Eigen/QR>
|
||||
#include "solverbase.h"
|
||||
|
||||
template<typename MatrixType, int UpLo>
|
||||
typename MatrixType::RealScalar matrix_l1_norm(const MatrixType& m) {
|
||||
if(m.cols()==0) return typename MatrixType::RealScalar(0);
|
||||
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)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
MatrixType symmLo = symm.template triangularView<Lower>();
|
||||
MatrixType symmUp = symm.template triangularView<Upper>();
|
||||
MatrixType symmCpy = symm;
|
||||
|
||||
CholType<MatrixType,Lower> chollo(symmLo);
|
||||
CholType<MatrixType,Upper> cholup(symmUp);
|
||||
|
||||
for (int k=0; k<10; ++k)
|
||||
{
|
||||
VectorType vec = VectorType::Random(symm.rows());
|
||||
RealScalar sigma = internal::random<RealScalar>();
|
||||
symmCpy += sigma * vec * vec.adjoint();
|
||||
|
||||
// we are doing some downdates, so it might be the case that the matrix is not SPD anymore
|
||||
CholType<MatrixType,Lower> chol(symmCpy);
|
||||
if(chol.info()!=Success)
|
||||
break;
|
||||
|
||||
chollo.rankUpdate(vec, sigma);
|
||||
VERIFY_IS_APPROX(symmCpy, chollo.reconstructedMatrix());
|
||||
|
||||
cholup.rankUpdate(vec, sigma);
|
||||
VERIFY_IS_APPROX(symmCpy, cholup.reconstructedMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType> void cholesky(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
LLT.h LDLT.h
|
||||
*/
|
||||
Index rows = m.rows();
|
||||
Index 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
|
||||
for (int k=0; k<3; ++k)
|
||||
{
|
||||
MatrixType a1 = MatrixType::Random(rows,cols);
|
||||
symm += a1 * a1.adjoint();
|
||||
}
|
||||
|
||||
{
|
||||
STATIC_CHECK(( internal::is_same<typename LLT<MatrixType,Lower>::StorageIndex,int>::value ));
|
||||
STATIC_CHECK(( internal::is_same<typename LLT<MatrixType,Upper>::StorageIndex,int>::value ));
|
||||
|
||||
SquareMatrixType symmUp = symm.template triangularView<Upper>();
|
||||
SquareMatrixType symmLo = symm.template triangularView<Lower>();
|
||||
|
||||
LLT<SquareMatrixType,Lower> chollo(symmLo);
|
||||
VERIFY_IS_APPROX(symm, chollo.reconstructedMatrix());
|
||||
|
||||
check_solverbase<VectorType, VectorType>(symm, chollo, rows, rows, 1);
|
||||
check_solverbase<MatrixType, MatrixType>(symm, chollo, rows, cols, rows);
|
||||
|
||||
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());
|
||||
vecX = cholup.solve(vecB);
|
||||
VERIFY_IS_APPROX(symm * vecX, vecB);
|
||||
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(neg.size()==0 || chollo.info()==NumericalIssue);
|
||||
|
||||
VERIFY_IS_APPROX(MatrixType(chollo.matrixL().transpose().conjugate()), MatrixType(chollo.matrixU()));
|
||||
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;
|
||||
m2 += symmLo.template selfadjointView<Lower>().llt().solve(matB);
|
||||
VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
|
||||
m2 = m1;
|
||||
m2 -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
|
||||
VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
|
||||
m2 = m1;
|
||||
m2.noalias() += symmLo.template selfadjointView<Lower>().llt().solve(matB);
|
||||
VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
|
||||
m2 = m1;
|
||||
m2.noalias() -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
|
||||
VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
|
||||
}
|
||||
|
||||
// LDLT
|
||||
{
|
||||
STATIC_CHECK(( internal::is_same<typename LDLT<MatrixType,Lower>::StorageIndex,int>::value ));
|
||||
STATIC_CHECK(( internal::is_same<typename LDLT<MatrixType,Upper>::StorageIndex,int>::value ));
|
||||
|
||||
int sign = internal::random<int>()%2 ? 1 : -1;
|
||||
|
||||
if(sign == -1)
|
||||
{
|
||||
symm = -symm; // test a negative matrix
|
||||
}
|
||||
|
||||
SquareMatrixType symmUp = symm.template triangularView<Upper>();
|
||||
SquareMatrixType symmLo = symm.template triangularView<Lower>();
|
||||
|
||||
LDLT<SquareMatrixType,Lower> ldltlo(symmLo);
|
||||
VERIFY(ldltlo.info()==Success);
|
||||
VERIFY_IS_APPROX(symm, ldltlo.reconstructedMatrix());
|
||||
|
||||
check_solverbase<VectorType, VectorType>(symm, ldltlo, rows, rows, 1);
|
||||
check_solverbase<MatrixType, MatrixType>(symm, ldltlo, rows, cols, rows);
|
||||
|
||||
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()));
|
||||
VERIFY_IS_APPROX(MatrixType(ldltup.matrixU().transpose().conjugate()), MatrixType(ldltup.matrixL()));
|
||||
|
||||
if(MatrixType::RowsAtCompileTime==Dynamic)
|
||||
{
|
||||
// note : each inplace permutation requires a small temporary vector (mask)
|
||||
|
||||
// check inplace solve
|
||||
matX = matB;
|
||||
VERIFY_EVALUATION_COUNT(matX = ldltlo.solve(matX), 0);
|
||||
VERIFY_IS_APPROX(matX, ldltlo.solve(matB).eval());
|
||||
|
||||
|
||||
matX = matB;
|
||||
VERIFY_EVALUATION_COUNT(matX = ldltup.solve(matX), 0);
|
||||
VERIFY_IS_APPROX(matX, ldltup.solve(matB).eval());
|
||||
}
|
||||
|
||||
// restore
|
||||
if(sign == -1)
|
||||
symm = -symm;
|
||||
|
||||
// check matrices coming from linear constraints with Lagrange multipliers
|
||||
if(rows>=3)
|
||||
{
|
||||
SquareMatrixType A = symm;
|
||||
Index c = internal::random<Index>(0,rows-2);
|
||||
A.bottomRightCorner(c,c).setZero();
|
||||
// Make sure a solution exists:
|
||||
vecX.setRandom();
|
||||
vecB = A * vecX;
|
||||
vecX.setZero();
|
||||
ldltlo.compute(A);
|
||||
VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
|
||||
vecX = ldltlo.solve(vecB);
|
||||
VERIFY_IS_APPROX(A * vecX, vecB);
|
||||
}
|
||||
|
||||
// check non-full rank matrices
|
||||
if(rows>=3)
|
||||
{
|
||||
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:
|
||||
vecX.setRandom();
|
||||
vecB = A * vecX;
|
||||
vecX.setZero();
|
||||
ldltlo.compute(A);
|
||||
VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
|
||||
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(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();
|
||||
vecB = A * vecX;
|
||||
vecX.setZero();
|
||||
ldltlo.compute(A);
|
||||
VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
|
||||
vecX = ldltlo.solve(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update/downdate
|
||||
CALL_SUBTEST(( test_chol_update<SquareMatrixType,LLT>(symm) ));
|
||||
CALL_SUBTEST(( test_chol_update<SquareMatrixType,LDLT>(symm) ));
|
||||
}
|
||||
|
||||
template<typename MatrixType> void cholesky_cplx(const MatrixType& m)
|
||||
{
|
||||
// classic test
|
||||
cholesky(m);
|
||||
|
||||
// test mixing real/scalar types
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> RealMatrixType;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
RealMatrixType a0 = RealMatrixType::Random(rows,cols);
|
||||
VectorType vecB = VectorType::Random(rows), vecX(rows);
|
||||
MatrixType matB = MatrixType::Random(rows,cols), matX(rows,cols);
|
||||
RealMatrixType symm = a0 * a0.adjoint();
|
||||
// let's make sure the matrix is not singular or near singular
|
||||
for (int k=0; k<3; ++k)
|
||||
{
|
||||
RealMatrixType a1 = RealMatrixType::Random(rows,cols);
|
||||
symm += a1 * a1.adjoint();
|
||||
}
|
||||
|
||||
{
|
||||
RealMatrixType symmLo = symm.template triangularView<Lower>();
|
||||
|
||||
LLT<RealMatrixType,Lower> chollo(symmLo);
|
||||
VERIFY_IS_APPROX(symm, chollo.reconstructedMatrix());
|
||||
|
||||
check_solverbase<VectorType, VectorType>(symm, chollo, rows, rows, 1);
|
||||
//check_solverbase<MatrixType, MatrixType>(symm, chollo, rows, cols, rows);
|
||||
}
|
||||
|
||||
// LDLT
|
||||
{
|
||||
int sign = internal::random<int>()%2 ? 1 : -1;
|
||||
|
||||
if(sign == -1)
|
||||
{
|
||||
symm = -symm; // test a negative matrix
|
||||
}
|
||||
|
||||
RealMatrixType symmLo = symm.template triangularView<Lower>();
|
||||
|
||||
LDLT<RealMatrixType,Lower> ldltlo(symmLo);
|
||||
VERIFY(ldltlo.info()==Success);
|
||||
VERIFY_IS_APPROX(symm, ldltlo.reconstructedMatrix());
|
||||
|
||||
check_solverbase<VectorType, VectorType>(symm, ldltlo, rows, rows, 1);
|
||||
//check_solverbase<MatrixType, MatrixType>(symm, ldltlo, rows, cols, rows);
|
||||
}
|
||||
}
|
||||
|
||||
// regression test for bug 241
|
||||
template<typename MatrixType> void cholesky_bug241(const MatrixType& m)
|
||||
{
|
||||
eigen_assert(m.rows() == 2 && m.cols() == 2);
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
MatrixType matA;
|
||||
matA << 1, 1, 1, 1;
|
||||
VectorType vecB;
|
||||
vecB << 1, 1;
|
||||
VectorType vecX = matA.ldlt().solve(vecB);
|
||||
VERIFY_IS_APPROX(matA * vecX, vecB);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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());
|
||||
VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
|
||||
}
|
||||
{
|
||||
mat << 1, 2, 2, 1;
|
||||
ldlt.compute(mat);
|
||||
VERIFY(ldlt.info()==Success);
|
||||
VERIFY(!ldlt.isNegative());
|
||||
VERIFY(!ldlt.isPositive());
|
||||
VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
|
||||
}
|
||||
{
|
||||
mat << 0, 0, 0, 0;
|
||||
ldlt.compute(mat);
|
||||
VERIFY(ldlt.info()==Success);
|
||||
VERIFY(ldlt.isNegative());
|
||||
VERIFY(ldlt.isPositive());
|
||||
VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
|
||||
}
|
||||
{
|
||||
mat << 0, 0, 0, 1;
|
||||
ldlt.compute(mat);
|
||||
VERIFY(ldlt.info()==Success);
|
||||
VERIFY(!ldlt.isNegative());
|
||||
VERIFY(ldlt.isPositive());
|
||||
VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
|
||||
}
|
||||
{
|
||||
mat << -1, 0, 0, 0;
|
||||
ldlt.compute(mat);
|
||||
VERIFY(ldlt.info()==Success);
|
||||
VERIFY(ldlt.isNegative());
|
||||
VERIFY(!ldlt.isPositive());
|
||||
VERIFY_IS_APPROX(mat,ldlt.reconstructedMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
// bug 1479
|
||||
{
|
||||
mat.resize(4,4);
|
||||
mat << 1, 2, 0, 1,
|
||||
2, 4, 0, 2,
|
||||
0, 0, 0, 1,
|
||||
1, 2, 1, 1;
|
||||
ldlt.compute(mat);
|
||||
VERIFY(ldlt.info()==NumericalIssue);
|
||||
VERIFY_IS_NOT_APPROX(mat,ldlt.reconstructedMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType> void cholesky_verify_assert()
|
||||
{
|
||||
MatrixType tmp;
|
||||
|
||||
LLT<MatrixType> llt;
|
||||
VERIFY_RAISES_ASSERT(llt.matrixL())
|
||||
VERIFY_RAISES_ASSERT(llt.matrixU())
|
||||
VERIFY_RAISES_ASSERT(llt.solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(llt.transpose().solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(llt.adjoint().solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(llt.solveInPlace(tmp))
|
||||
|
||||
LDLT<MatrixType> ldlt;
|
||||
VERIFY_RAISES_ASSERT(ldlt.matrixL())
|
||||
VERIFY_RAISES_ASSERT(ldlt.transpositionsP())
|
||||
VERIFY_RAISES_ASSERT(ldlt.vectorD())
|
||||
VERIFY_RAISES_ASSERT(ldlt.isPositive())
|
||||
VERIFY_RAISES_ASSERT(ldlt.isNegative())
|
||||
VERIFY_RAISES_ASSERT(ldlt.solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(ldlt.transpose().solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(ldlt.adjoint().solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(ldlt.solveInPlace(tmp))
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(cholesky)
|
||||
{
|
||||
int s = 0;
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( cholesky(Matrix<double,1,1>()) );
|
||||
CALL_SUBTEST_3( cholesky(Matrix2d()) );
|
||||
CALL_SUBTEST_3( cholesky_bug241(Matrix2d()) );
|
||||
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)
|
||||
}
|
||||
// empty matrix, regression test for Bug 785:
|
||||
CALL_SUBTEST_2( cholesky(MatrixXd(0,0)) );
|
||||
|
||||
// This does not work yet:
|
||||
// CALL_SUBTEST_2( cholesky(Matrix<double,0,0>()) );
|
||||
|
||||
CALL_SUBTEST_4( cholesky_verify_assert<Matrix3f>() );
|
||||
CALL_SUBTEST_7( cholesky_verify_assert<Matrix3d>() );
|
||||
CALL_SUBTEST_8( cholesky_verify_assert<MatrixXf>() );
|
||||
CALL_SUBTEST_2( cholesky_verify_assert<MatrixXd>() );
|
||||
|
||||
// Test problem size constructors
|
||||
CALL_SUBTEST_9( LLT<MatrixXf>(10) );
|
||||
CALL_SUBTEST_9( LDLT<MatrixXf>(10) );
|
||||
|
||||
CALL_SUBTEST_2( cholesky_faillure_cases<void>() );
|
||||
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(nb_temporaries)
|
||||
}
|
||||
69
libs/eigen/test/cholmod_support.cpp
Normal file
69
libs/eigen/test/cholmod_support.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
// 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/.
|
||||
|
||||
#define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
|
||||
#include "sparse_solver.h"
|
||||
|
||||
#include <Eigen/CholmodSupport>
|
||||
|
||||
template<typename SparseType> void test_cholmod_ST()
|
||||
{
|
||||
CholmodDecomposition<SparseType, Lower> g_chol_colmajor_lower; g_chol_colmajor_lower.setMode(CholmodSupernodalLLt);
|
||||
CholmodDecomposition<SparseType, Upper> g_chol_colmajor_upper; g_chol_colmajor_upper.setMode(CholmodSupernodalLLt);
|
||||
CholmodDecomposition<SparseType, Lower> g_llt_colmajor_lower; g_llt_colmajor_lower.setMode(CholmodSimplicialLLt);
|
||||
CholmodDecomposition<SparseType, Upper> g_llt_colmajor_upper; g_llt_colmajor_upper.setMode(CholmodSimplicialLLt);
|
||||
CholmodDecomposition<SparseType, Lower> g_ldlt_colmajor_lower; g_ldlt_colmajor_lower.setMode(CholmodLDLt);
|
||||
CholmodDecomposition<SparseType, Upper> g_ldlt_colmajor_upper; g_ldlt_colmajor_upper.setMode(CholmodLDLt);
|
||||
|
||||
CholmodSupernodalLLT<SparseType, Lower> chol_colmajor_lower;
|
||||
CholmodSupernodalLLT<SparseType, Upper> chol_colmajor_upper;
|
||||
CholmodSimplicialLLT<SparseType, Lower> llt_colmajor_lower;
|
||||
CholmodSimplicialLLT<SparseType, Upper> llt_colmajor_upper;
|
||||
CholmodSimplicialLDLT<SparseType, Lower> ldlt_colmajor_lower;
|
||||
CholmodSimplicialLDLT<SparseType, Upper> ldlt_colmajor_upper;
|
||||
|
||||
check_sparse_spd_solving(g_chol_colmajor_lower);
|
||||
check_sparse_spd_solving(g_chol_colmajor_upper);
|
||||
check_sparse_spd_solving(g_llt_colmajor_lower);
|
||||
check_sparse_spd_solving(g_llt_colmajor_upper);
|
||||
check_sparse_spd_solving(g_ldlt_colmajor_lower);
|
||||
check_sparse_spd_solving(g_ldlt_colmajor_upper);
|
||||
|
||||
check_sparse_spd_solving(chol_colmajor_lower);
|
||||
check_sparse_spd_solving(chol_colmajor_upper);
|
||||
check_sparse_spd_solving(llt_colmajor_lower);
|
||||
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);
|
||||
}
|
||||
|
||||
template<typename T, int flags, typename IdxType> void test_cholmod_T()
|
||||
{
|
||||
test_cholmod_ST<SparseMatrix<T, flags, IdxType> >();
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(cholmod_support)
|
||||
{
|
||||
CALL_SUBTEST_11( (test_cholmod_T<double , ColMajor, int >()) );
|
||||
CALL_SUBTEST_12( (test_cholmod_T<double , ColMajor, long>()) );
|
||||
CALL_SUBTEST_13( (test_cholmod_T<double , RowMajor, int >()) );
|
||||
CALL_SUBTEST_14( (test_cholmod_T<double , RowMajor, long>()) );
|
||||
CALL_SUBTEST_21( (test_cholmod_T<std::complex<double>, ColMajor, int >()) );
|
||||
CALL_SUBTEST_22( (test_cholmod_T<std::complex<double>, ColMajor, long>()) );
|
||||
// TODO complex row-major matrices do not work at the moment:
|
||||
// CALL_SUBTEST_23( (test_cholmod_T<std::complex<double>, RowMajor, int >()) );
|
||||
// CALL_SUBTEST_24( (test_cholmod_T<std::complex<double>, RowMajor, long>()) );
|
||||
}
|
||||
118
libs/eigen/test/commainitializer.cpp
Normal file
118
libs/eigen/test/commainitializer.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 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"
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
if(M1 > 0)
|
||||
{
|
||||
VERIFY_RAISES_ASSERT((m_fixed << mat11, mat12, mat11, mat21, mat22));
|
||||
}
|
||||
if(M2 > 0)
|
||||
{
|
||||
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 depth, int N=0>
|
||||
struct test_block_recursion
|
||||
{
|
||||
static void run()
|
||||
{
|
||||
test_block_recursion<depth-1, N>::run();
|
||||
test_block_recursion<depth-1, N + (1 << (depth-1))>::run();
|
||||
}
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct test_block_recursion<0,N>
|
||||
{
|
||||
static void run() {
|
||||
test_blocks<(N>>6)&3, (N>>4)&3, (N>>2)&3, N & 3>();
|
||||
}
|
||||
};
|
||||
|
||||
void test_basics() {
|
||||
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);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(commainitializer)
|
||||
{
|
||||
|
||||
CALL_SUBTEST_1(test_basics());
|
||||
|
||||
// recursively test all block-sizes from 0 to 3:
|
||||
CALL_SUBTEST_2(test_block_recursion<8>::run());
|
||||
}
|
||||
34
libs/eigen/test/conjugate_gradient.cpp
Normal file
34
libs/eigen/test/conjugate_gradient.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
// 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, typename I_> void test_conjugate_gradient_T()
|
||||
{
|
||||
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) );
|
||||
CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_loup_diag) );
|
||||
CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_lower_I) );
|
||||
CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_upper_I) );
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(conjugate_gradient)
|
||||
{
|
||||
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>() ));
|
||||
}
|
||||
167
libs/eigen/test/conservative_resize.cpp
Normal file
167
libs/eigen/test/conservative_resize.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 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>
|
||||
#include "AnnoyingScalar.h"
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
template <typename Scalar, int Storage>
|
||||
void run_matrix_tests()
|
||||
{
|
||||
typedef Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Storage> MatrixType;
|
||||
|
||||
MatrixType m, n;
|
||||
|
||||
// boundary cases ...
|
||||
m = n = MatrixType::Random(50,50);
|
||||
m.conservativeResize(1,50);
|
||||
VERIFY_IS_APPROX(m, n.block(0,0,1,50));
|
||||
|
||||
m = n = MatrixType::Random(50,50);
|
||||
m.conservativeResize(50,1);
|
||||
VERIFY_IS_APPROX(m, n.block(0,0,50,1));
|
||||
|
||||
m = n = MatrixType::Random(50,50);
|
||||
m.conservativeResize(50,50);
|
||||
VERIFY_IS_APPROX(m, n.block(0,0,50,50));
|
||||
|
||||
// random shrinking ...
|
||||
for (int i=0; i<25; ++i)
|
||||
{
|
||||
const Index rows = internal::random<Index>(1,50);
|
||||
const Index cols = internal::random<Index>(1,50);
|
||||
m = n = MatrixType::Random(50,50);
|
||||
m.conservativeResize(rows,cols);
|
||||
VERIFY_IS_APPROX(m, n.block(0,0,rows,cols));
|
||||
}
|
||||
|
||||
// random growing with zeroing ...
|
||||
for (int i=0; i<25; ++i)
|
||||
{
|
||||
const Index rows = internal::random<Index>(50,75);
|
||||
const Index cols = internal::random<Index>(50,75);
|
||||
m = n = MatrixType::Random(50,50);
|
||||
m.conservativeResizeLike(MatrixType::Zero(rows,cols));
|
||||
VERIFY_IS_APPROX(m.block(0,0,n.rows(),n.cols()), n);
|
||||
VERIFY( rows<=50 || m.block(50,0,rows-50,cols).sum() == Scalar(0) );
|
||||
VERIFY( cols<=50 || m.block(0,50,rows,cols-50).sum() == Scalar(0) );
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
void run_vector_tests()
|
||||
{
|
||||
typedef Matrix<Scalar, 1, Eigen::Dynamic> VectorType;
|
||||
|
||||
VectorType m, n;
|
||||
|
||||
// boundary cases ...
|
||||
m = n = VectorType::Random(50);
|
||||
m.conservativeResize(1);
|
||||
VERIFY_IS_APPROX(m, n.segment(0,1));
|
||||
|
||||
m = n = VectorType::Random(50);
|
||||
m.conservativeResize(50);
|
||||
VERIFY_IS_APPROX(m, n.segment(0,50));
|
||||
|
||||
m = n = VectorType::Random(50);
|
||||
m.conservativeResize(m.rows(),1);
|
||||
VERIFY_IS_APPROX(m, n.segment(0,1));
|
||||
|
||||
m = n = VectorType::Random(50);
|
||||
m.conservativeResize(m.rows(),50);
|
||||
VERIFY_IS_APPROX(m, n.segment(0,50));
|
||||
|
||||
// random shrinking ...
|
||||
for (int i=0; i<50; ++i)
|
||||
{
|
||||
const int size = internal::random<int>(1,50);
|
||||
m = n = VectorType::Random(50);
|
||||
m.conservativeResize(size);
|
||||
VERIFY_IS_APPROX(m, n.segment(0,size));
|
||||
|
||||
m = n = VectorType::Random(50);
|
||||
m.conservativeResize(m.rows(), size);
|
||||
VERIFY_IS_APPROX(m, n.segment(0,size));
|
||||
}
|
||||
|
||||
// random growing with zeroing ...
|
||||
for (int i=0; i<50; ++i)
|
||||
{
|
||||
const int size = internal::random<int>(50,100);
|
||||
m = n = VectorType::Random(50);
|
||||
m.conservativeResizeLike(VectorType::Zero(size));
|
||||
VERIFY_IS_APPROX(m.segment(0,50), n);
|
||||
VERIFY( size<=50 || m.segment(50,size-50).sum() == Scalar(0) );
|
||||
|
||||
m = n = VectorType::Random(50);
|
||||
m.conservativeResizeLike(Matrix<Scalar,Dynamic,Dynamic>::Zero(1,size));
|
||||
VERIFY_IS_APPROX(m.segment(0,50), n);
|
||||
VERIFY( size<=50 || m.segment(50,size-50).sum() == Scalar(0) );
|
||||
}
|
||||
}
|
||||
|
||||
// Basic memory leak check with a non-copyable scalar type
|
||||
template<int> void noncopyable()
|
||||
{
|
||||
typedef Eigen::Matrix<AnnoyingScalar,Dynamic,1> VectorType;
|
||||
typedef Eigen::Matrix<AnnoyingScalar,Dynamic,Dynamic> MatrixType;
|
||||
|
||||
{
|
||||
#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
|
||||
AnnoyingScalar::dont_throw = true;
|
||||
#endif
|
||||
int n = 50;
|
||||
VectorType v0(n), v1(n);
|
||||
MatrixType m0(n,n), m1(n,n), m2(n,n);
|
||||
v0.setOnes(); v1.setOnes();
|
||||
m0.setOnes(); m1.setOnes(); m2.setOnes();
|
||||
VERIFY(m0==m1);
|
||||
m0.conservativeResize(2*n,2*n);
|
||||
VERIFY(m0.topLeftCorner(n,n) == m1);
|
||||
|
||||
VERIFY(v0.head(n) == v1);
|
||||
v0.conservativeResize(2*n);
|
||||
VERIFY(v0.head(n) == v1);
|
||||
}
|
||||
VERIFY(AnnoyingScalar::instances==0 && "global memory leak detected in noncopyable");
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(conservative_resize)
|
||||
{
|
||||
for(int i=0; i<g_repeat; ++i)
|
||||
{
|
||||
CALL_SUBTEST_1((run_matrix_tests<int, Eigen::RowMajor>()));
|
||||
CALL_SUBTEST_1((run_matrix_tests<int, Eigen::ColMajor>()));
|
||||
CALL_SUBTEST_2((run_matrix_tests<float, Eigen::RowMajor>()));
|
||||
CALL_SUBTEST_2((run_matrix_tests<float, Eigen::ColMajor>()));
|
||||
CALL_SUBTEST_3((run_matrix_tests<double, Eigen::RowMajor>()));
|
||||
CALL_SUBTEST_3((run_matrix_tests<double, Eigen::ColMajor>()));
|
||||
CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::RowMajor>()));
|
||||
CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::ColMajor>()));
|
||||
CALL_SUBTEST_5((run_matrix_tests<std::complex<double>, Eigen::RowMajor>()));
|
||||
CALL_SUBTEST_5((run_matrix_tests<std::complex<double>, Eigen::ColMajor>()));
|
||||
CALL_SUBTEST_1((run_matrix_tests<int, Eigen::RowMajor | Eigen::DontAlign>()));
|
||||
|
||||
CALL_SUBTEST_1((run_vector_tests<int>()));
|
||||
CALL_SUBTEST_2((run_vector_tests<float>()));
|
||||
CALL_SUBTEST_3((run_vector_tests<double>()));
|
||||
CALL_SUBTEST_4((run_vector_tests<std::complex<float> >()));
|
||||
CALL_SUBTEST_5((run_vector_tests<std::complex<double> >()));
|
||||
|
||||
#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
|
||||
AnnoyingScalar::dont_throw = true;
|
||||
#endif
|
||||
CALL_SUBTEST_6(( run_vector_tests<AnnoyingScalar>() ));
|
||||
CALL_SUBTEST_6(( noncopyable<0>() ));
|
||||
}
|
||||
}
|
||||
98
libs/eigen/test/constructor.cpp
Normal file
98
libs/eigen/test/constructor.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
// 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; }
|
||||
};
|
||||
|
||||
enum my_sizes { M = 12, N = 7};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DECLARE_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);
|
||||
}
|
||||
{
|
||||
MatrixXi m1(M,N);
|
||||
VERIFY_IS_EQUAL(m1.rows(),M);
|
||||
VERIFY_IS_EQUAL(m1.cols(),N);
|
||||
ArrayXXi a1(M,N);
|
||||
VERIFY_IS_EQUAL(a1.rows(),M);
|
||||
VERIFY_IS_EQUAL(a1.cols(),N);
|
||||
VectorXi v1(M);
|
||||
VERIFY_IS_EQUAL(v1.size(),M);
|
||||
ArrayXi a2(M);
|
||||
VERIFY_IS_EQUAL(a2.size(),M);
|
||||
}
|
||||
}
|
||||
117
libs/eigen/test/corners.cpp
Normal file
117
libs/eigen/test/corners.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-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"
|
||||
|
||||
#define COMPARE_CORNER(A,B) \
|
||||
VERIFY_IS_EQUAL(matrix.A, matrix.B); \
|
||||
VERIFY_IS_EQUAL(const_matrix.A, const_matrix.B);
|
||||
|
||||
template<typename MatrixType> void corners(const MatrixType& m)
|
||||
{
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
Index r = internal::random<Index>(1,rows);
|
||||
Index c = internal::random<Index>(1,cols);
|
||||
|
||||
MatrixType matrix = MatrixType::Random(rows,cols);
|
||||
const MatrixType const_matrix = MatrixType::Random(rows,cols);
|
||||
|
||||
COMPARE_CORNER(topLeftCorner(r,c), block(0,0,r,c));
|
||||
COMPARE_CORNER(topRightCorner(r,c), block(0,cols-c,r,c));
|
||||
COMPARE_CORNER(bottomLeftCorner(r,c), block(rows-r,0,r,c));
|
||||
COMPARE_CORNER(bottomRightCorner(r,c), block(rows-r,cols-c,r,c));
|
||||
|
||||
Index sr = internal::random<Index>(1,rows) - 1;
|
||||
Index nr = internal::random<Index>(1,rows-sr);
|
||||
Index sc = internal::random<Index>(1,cols) - 1;
|
||||
Index nc = internal::random<Index>(1,cols-sc);
|
||||
|
||||
COMPARE_CORNER(topRows(r), block(0,0,r,cols));
|
||||
COMPARE_CORNER(middleRows(sr,nr), block(sr,0,nr,cols));
|
||||
COMPARE_CORNER(bottomRows(r), block(rows-r,0,r,cols));
|
||||
COMPARE_CORNER(leftCols(c), block(0,0,rows,c));
|
||||
COMPARE_CORNER(middleCols(sc,nc), block(0,sc,rows,nc));
|
||||
COMPARE_CORNER(rightCols(c), block(0,cols-c,rows,c));
|
||||
}
|
||||
|
||||
template<typename MatrixType, int CRows, int CCols, int SRows, int SCols> void corners_fixedsize()
|
||||
{
|
||||
MatrixType matrix = MatrixType::Random();
|
||||
const MatrixType const_matrix = MatrixType::Random();
|
||||
|
||||
enum {
|
||||
rows = MatrixType::RowsAtCompileTime,
|
||||
cols = MatrixType::ColsAtCompileTime,
|
||||
r = CRows,
|
||||
c = CCols,
|
||||
sr = SRows,
|
||||
sc = SCols
|
||||
};
|
||||
|
||||
VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template block<r,c>(0,0)));
|
||||
VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template block<r,c>(0,cols-c)));
|
||||
VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template block<r,c>(rows-r,0)));
|
||||
VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template block<r,c>(rows-r,cols-c)));
|
||||
|
||||
VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template topLeftCorner<r,Dynamic>(r,c)));
|
||||
VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template topRightCorner<r,Dynamic>(r,c)));
|
||||
VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template bottomLeftCorner<r,Dynamic>(r,c)));
|
||||
VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template bottomRightCorner<r,Dynamic>(r,c)));
|
||||
|
||||
VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template topLeftCorner<Dynamic,c>(r,c)));
|
||||
VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template topRightCorner<Dynamic,c>(r,c)));
|
||||
VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template bottomLeftCorner<Dynamic,c>(r,c)));
|
||||
VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template bottomRightCorner<Dynamic,c>(r,c)));
|
||||
|
||||
VERIFY_IS_EQUAL((matrix.template topRows<r>()), (matrix.template block<r,cols>(0,0)));
|
||||
VERIFY_IS_EQUAL((matrix.template middleRows<r>(sr)), (matrix.template block<r,cols>(sr,0)));
|
||||
VERIFY_IS_EQUAL((matrix.template bottomRows<r>()), (matrix.template block<r,cols>(rows-r,0)));
|
||||
VERIFY_IS_EQUAL((matrix.template leftCols<c>()), (matrix.template block<rows,c>(0,0)));
|
||||
VERIFY_IS_EQUAL((matrix.template middleCols<c>(sc)), (matrix.template block<rows,c>(0,sc)));
|
||||
VERIFY_IS_EQUAL((matrix.template rightCols<c>()), (matrix.template block<rows,c>(0,cols-c)));
|
||||
|
||||
VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template block<r,c>(0,0)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template block<r,c>(0,cols-c)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template block<r,c>(rows-r,0)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template block<r,c>(rows-r,cols-c)));
|
||||
|
||||
VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template topLeftCorner<r,Dynamic>(r,c)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template topRightCorner<r,Dynamic>(r,c)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template bottomLeftCorner<r,Dynamic>(r,c)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template bottomRightCorner<r,Dynamic>(r,c)));
|
||||
|
||||
VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template topLeftCorner<Dynamic,c>(r,c)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template topRightCorner<Dynamic,c>(r,c)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template bottomLeftCorner<Dynamic,c>(r,c)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template bottomRightCorner<Dynamic,c>(r,c)));
|
||||
|
||||
VERIFY_IS_EQUAL((const_matrix.template topRows<r>()), (const_matrix.template block<r,cols>(0,0)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template middleRows<r>(sr)), (const_matrix.template block<r,cols>(sr,0)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template bottomRows<r>()), (const_matrix.template block<r,cols>(rows-r,0)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template leftCols<c>()), (const_matrix.template block<rows,c>(0,0)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template middleCols<c>(sc)), (const_matrix.template block<rows,c>(0,sc)));
|
||||
VERIFY_IS_EQUAL((const_matrix.template rightCols<c>()), (const_matrix.template block<rows,c>(0,cols-c)));
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(corners)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( corners(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( corners(Matrix4d()) );
|
||||
CALL_SUBTEST_3( corners(Matrix<int,10,12>()) );
|
||||
CALL_SUBTEST_4( corners(MatrixXcf(5, 7)) );
|
||||
CALL_SUBTEST_5( corners(MatrixXf(21, 20)) );
|
||||
|
||||
CALL_SUBTEST_1(( corners_fixedsize<Matrix<float, 1, 1>, 1, 1, 0, 0>() ));
|
||||
CALL_SUBTEST_2(( corners_fixedsize<Matrix4d,2,2,1,1>() ));
|
||||
CALL_SUBTEST_3(( corners_fixedsize<Matrix<int,10,12>,4,7,5,2>() ));
|
||||
}
|
||||
}
|
||||
81
libs/eigen/test/ctorleak.cpp
Normal file
81
libs/eigen/test/ctorleak.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "main.h"
|
||||
|
||||
#include <exception> // std::exception
|
||||
|
||||
struct Foo
|
||||
{
|
||||
static Index object_count;
|
||||
static Index object_limit;
|
||||
int dummy;
|
||||
|
||||
Foo() : dummy(0)
|
||||
{
|
||||
#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
|
||||
|
||||
EIGEN_DECLARE_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 = rows*cols;
|
||||
{
|
||||
MatrixX r(rows, cols);
|
||||
Foo::object_limit = r.size()+internal::random<Index>(0, rows*cols - 2);
|
||||
std::cout << "object_limit =" << Foo::object_limit << std::endl;
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif
|
||||
if(internal::random<bool>()) {
|
||||
std::cout << "\nMatrixX m(" << rows << ", " << cols << ");\n";
|
||||
MatrixX m(rows, cols);
|
||||
}
|
||||
else {
|
||||
std::cout << "\nMatrixX m(r);\n";
|
||||
MatrixX m(r);
|
||||
}
|
||||
#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);
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
190
libs/eigen/test/denseLM.cpp
Normal file
190
libs/eigen/test/denseLM.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
|
||||
// Copyright (C) 2012 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 <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/LevenbergMarquardt>
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
|
||||
template<typename Scalar>
|
||||
struct DenseLM : DenseFunctor<Scalar>
|
||||
{
|
||||
typedef DenseFunctor<Scalar> Base;
|
||||
typedef typename Base::JacobianType JacobianType;
|
||||
typedef Matrix<Scalar,Dynamic,1> VectorType;
|
||||
|
||||
DenseLM(int n, int m) : DenseFunctor<Scalar>(n,m)
|
||||
{ }
|
||||
|
||||
VectorType model(const VectorType& uv, VectorType& x)
|
||||
{
|
||||
VectorType y; // Should change to use expression template
|
||||
int m = Base::values();
|
||||
int n = Base::inputs();
|
||||
eigen_assert(uv.size()%2 == 0);
|
||||
eigen_assert(uv.size() == n);
|
||||
eigen_assert(x.size() == m);
|
||||
y.setZero(m);
|
||||
int half = n/2;
|
||||
VectorBlock<const VectorType> u(uv, 0, half);
|
||||
VectorBlock<const VectorType> v(uv, half, half);
|
||||
for (int j = 0; j < m; j++)
|
||||
{
|
||||
for (int i = 0; i < half; i++)
|
||||
y(j) += u(i)*std::exp(-(x(j)-i)*(x(j)-i)/(v(i)*v(i)));
|
||||
}
|
||||
return y;
|
||||
|
||||
}
|
||||
void initPoints(VectorType& uv_ref, VectorType& x)
|
||||
{
|
||||
m_x = x;
|
||||
m_y = this->model(uv_ref, x);
|
||||
}
|
||||
|
||||
int operator()(const VectorType& uv, VectorType& fvec)
|
||||
{
|
||||
|
||||
int m = Base::values();
|
||||
int n = Base::inputs();
|
||||
eigen_assert(uv.size()%2 == 0);
|
||||
eigen_assert(uv.size() == n);
|
||||
eigen_assert(fvec.size() == m);
|
||||
int half = n/2;
|
||||
VectorBlock<const VectorType> u(uv, 0, half);
|
||||
VectorBlock<const VectorType> v(uv, half, half);
|
||||
for (int j = 0; j < m; j++)
|
||||
{
|
||||
fvec(j) = m_y(j);
|
||||
for (int i = 0; i < half; i++)
|
||||
{
|
||||
fvec(j) -= u(i) *std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int df(const VectorType& uv, JacobianType& fjac)
|
||||
{
|
||||
int m = Base::values();
|
||||
int n = Base::inputs();
|
||||
eigen_assert(n == uv.size());
|
||||
eigen_assert(fjac.rows() == m);
|
||||
eigen_assert(fjac.cols() == n);
|
||||
int half = n/2;
|
||||
VectorBlock<const VectorType> u(uv, 0, half);
|
||||
VectorBlock<const VectorType> v(uv, half, half);
|
||||
for (int j = 0; j < m; j++)
|
||||
{
|
||||
for (int i = 0; i < half; i++)
|
||||
{
|
||||
fjac.coeffRef(j,i) = -std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
|
||||
fjac.coeffRef(j,i+half) = -2.*u(i)*(m_x(j)-i)*(m_x(j)-i)/(std::pow(v(i),3)) * std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
VectorType m_x, m_y; //Data Points
|
||||
};
|
||||
|
||||
template<typename FunctorType, typename VectorType>
|
||||
int test_minimizeLM(FunctorType& functor, VectorType& uv)
|
||||
{
|
||||
LevenbergMarquardt<FunctorType> lm(functor);
|
||||
LevenbergMarquardtSpace::Status info;
|
||||
|
||||
info = lm.minimize(uv);
|
||||
|
||||
VERIFY_IS_EQUAL(info, 1);
|
||||
//FIXME Check other parameters
|
||||
return info;
|
||||
}
|
||||
|
||||
template<typename FunctorType, typename VectorType>
|
||||
int test_lmder(FunctorType& functor, VectorType& uv)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
LevenbergMarquardtSpace::Status info;
|
||||
LevenbergMarquardt<FunctorType> lm(functor);
|
||||
info = lm.lmder1(uv);
|
||||
|
||||
VERIFY_IS_EQUAL(info, 1);
|
||||
//FIXME Check other parameters
|
||||
return info;
|
||||
}
|
||||
|
||||
template<typename FunctorType, typename VectorType>
|
||||
int test_minimizeSteps(FunctorType& functor, VectorType& uv)
|
||||
{
|
||||
LevenbergMarquardtSpace::Status info;
|
||||
LevenbergMarquardt<FunctorType> lm(functor);
|
||||
info = lm.minimizeInit(uv);
|
||||
if (info==LevenbergMarquardtSpace::ImproperInputParameters)
|
||||
return info;
|
||||
do
|
||||
{
|
||||
info = lm.minimizeOneStep(uv);
|
||||
} while (info==LevenbergMarquardtSpace::Running);
|
||||
|
||||
VERIFY_IS_EQUAL(info, 1);
|
||||
//FIXME Check other parameters
|
||||
return info;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void test_denseLM_T()
|
||||
{
|
||||
typedef Matrix<T,Dynamic,1> VectorType;
|
||||
|
||||
int inputs = 10;
|
||||
int values = 1000;
|
||||
DenseLM<T> dense_gaussian(inputs, values);
|
||||
VectorType uv(inputs),uv_ref(inputs);
|
||||
VectorType x(values);
|
||||
|
||||
// Generate the reference solution
|
||||
uv_ref << -2, 1, 4 ,8, 6, 1.8, 1.2, 1.1, 1.9 , 3;
|
||||
|
||||
//Generate the reference data points
|
||||
x.setRandom();
|
||||
x = 10*x;
|
||||
x.array() += 10;
|
||||
dense_gaussian.initPoints(uv_ref, x);
|
||||
|
||||
// Generate the initial parameters
|
||||
VectorBlock<VectorType> u(uv, 0, inputs/2);
|
||||
VectorBlock<VectorType> v(uv, inputs/2, inputs/2);
|
||||
|
||||
// Solve the optimization problem
|
||||
|
||||
//Solve in one go
|
||||
u.setOnes(); v.setOnes();
|
||||
test_minimizeLM(dense_gaussian, uv);
|
||||
|
||||
//Solve until the machine precision
|
||||
u.setOnes(); v.setOnes();
|
||||
test_lmder(dense_gaussian, uv);
|
||||
|
||||
// Solve step by step
|
||||
v.setOnes(); u.setOnes();
|
||||
test_minimizeSteps(dense_gaussian, uv);
|
||||
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(denseLM)
|
||||
{
|
||||
CALL_SUBTEST_2(test_denseLM_T<double>());
|
||||
|
||||
// CALL_SUBTEST_2(test_sparseLM_T<std::complex<double>());
|
||||
}
|
||||
190
libs/eigen/test/dense_storage.cpp
Normal file
190
libs/eigen/test/dense_storage.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
// 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 "AnnoyingScalar.h"
|
||||
#include "SafeScalar.h"
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
#if EIGEN_HAS_TYPE_TRAITS && EIGEN_HAS_CXX11
|
||||
using DenseStorageD3x3 = Eigen::DenseStorage<double, 3, 3, 3, 3>;
|
||||
static_assert(std::is_trivially_move_constructible<DenseStorageD3x3>::value, "DenseStorage not trivially_move_constructible");
|
||||
static_assert(std::is_trivially_move_assignable<DenseStorageD3x3>::value, "DenseStorage not trivially_move_assignable");
|
||||
#if !defined(EIGEN_DENSE_STORAGE_CTOR_PLUGIN)
|
||||
static_assert(std::is_trivially_copy_constructible<DenseStorageD3x3>::value, "DenseStorage not trivially_copy_constructible");
|
||||
static_assert(std::is_trivially_copy_assignable<DenseStorageD3x3>::value, "DenseStorage not trivially_copy_assignable");
|
||||
static_assert(std::is_trivially_copyable<DenseStorageD3x3>::value, "DenseStorage not trivially_copyable");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <typename T, int Size, int Rows, int Cols>
|
||||
void dense_storage_copy(int rows, int cols)
|
||||
{
|
||||
typedef DenseStorage<T, Size, Rows, Cols, 0> DenseStorageType;
|
||||
|
||||
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 Size, int Rows, int Cols>
|
||||
void dense_storage_assignment(int rows, int cols)
|
||||
{
|
||||
typedef DenseStorage<T, Size, Rows, Cols, 0> DenseStorageType;
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
template <typename T, int Size, int Rows, int Cols>
|
||||
void dense_storage_swap(int rows0, int cols0, int rows1, int cols1)
|
||||
{
|
||||
typedef DenseStorage<T, Size, Rows, Cols, 0> DenseStorageType;
|
||||
|
||||
const int size0 = rows0*cols0;
|
||||
DenseStorageType a(size0, rows0, cols0);
|
||||
for (int i=0; i<size0; ++i) {
|
||||
a.data()[i] = static_cast<T>(i);
|
||||
}
|
||||
|
||||
const int size1 = rows1*cols1;
|
||||
DenseStorageType b(size1, rows1, cols1);
|
||||
for (int i=0; i<size1; ++i) {
|
||||
b.data()[i] = static_cast<T>(-i);
|
||||
}
|
||||
|
||||
a.swap(b);
|
||||
|
||||
for (int i=0; i<size0; ++i) {
|
||||
VERIFY_IS_EQUAL(b.data()[i], static_cast<T>(i));
|
||||
}
|
||||
|
||||
for (int i=0; i<size1; ++i) {
|
||||
VERIFY_IS_EQUAL(a.data()[i], static_cast<T>(-i));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, int Size, std::size_t Alignment>
|
||||
void dense_storage_alignment()
|
||||
{
|
||||
#if EIGEN_HAS_ALIGNAS
|
||||
|
||||
struct alignas(Alignment) Empty1 {};
|
||||
VERIFY_IS_EQUAL(std::alignment_of<Empty1>::value, Alignment);
|
||||
|
||||
struct EIGEN_ALIGN_TO_BOUNDARY(Alignment) Empty2 {};
|
||||
VERIFY_IS_EQUAL(std::alignment_of<Empty2>::value, Alignment);
|
||||
|
||||
struct Nested1 { EIGEN_ALIGN_TO_BOUNDARY(Alignment) T data[Size]; };
|
||||
VERIFY_IS_EQUAL(std::alignment_of<Nested1>::value, Alignment);
|
||||
|
||||
VERIFY_IS_EQUAL( (std::alignment_of<internal::plain_array<T,Size,AutoAlign,Alignment> >::value), Alignment);
|
||||
|
||||
const std::size_t default_alignment = internal::compute_default_alignment<T,Size>::value;
|
||||
|
||||
VERIFY_IS_EQUAL( (std::alignment_of<DenseStorage<T,Size,1,1,AutoAlign> >::value), default_alignment);
|
||||
VERIFY_IS_EQUAL( (std::alignment_of<Matrix<T,Size,1,AutoAlign> >::value), default_alignment);
|
||||
struct Nested2 { Matrix<T,Size,1,AutoAlign> mat; };
|
||||
VERIFY_IS_EQUAL(std::alignment_of<Nested2>::value, default_alignment);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void dense_storage_tests() {
|
||||
// Dynamic Storage.
|
||||
dense_storage_copy<T,Dynamic,Dynamic,Dynamic>(4, 3);
|
||||
dense_storage_copy<T,Dynamic,Dynamic,3>(4, 3);
|
||||
dense_storage_copy<T,Dynamic,4,Dynamic>(4, 3);
|
||||
// Fixed Storage.
|
||||
dense_storage_copy<T,12,4,3>(4, 3);
|
||||
dense_storage_copy<T,12,Dynamic,Dynamic>(4, 3);
|
||||
dense_storage_copy<T,12,4,Dynamic>(4, 3);
|
||||
dense_storage_copy<T,12,Dynamic,3>(4, 3);
|
||||
// Fixed Storage with Uninitialized Elements.
|
||||
dense_storage_copy<T,18,Dynamic,Dynamic>(4, 3);
|
||||
dense_storage_copy<T,18,4,Dynamic>(4, 3);
|
||||
dense_storage_copy<T,18,Dynamic,3>(4, 3);
|
||||
|
||||
// Dynamic Storage.
|
||||
dense_storage_assignment<T,Dynamic,Dynamic,Dynamic>(4, 3);
|
||||
dense_storage_assignment<T,Dynamic,Dynamic,3>(4, 3);
|
||||
dense_storage_assignment<T,Dynamic,4,Dynamic>(4, 3);
|
||||
// Fixed Storage.
|
||||
dense_storage_assignment<T,12,4,3>(4, 3);
|
||||
dense_storage_assignment<T,12,Dynamic,Dynamic>(4, 3);
|
||||
dense_storage_assignment<T,12,4,Dynamic>(4, 3);
|
||||
dense_storage_assignment<T,12,Dynamic,3>(4, 3);
|
||||
// Fixed Storage with Uninitialized Elements.
|
||||
dense_storage_assignment<T,18,Dynamic,Dynamic>(4, 3);
|
||||
dense_storage_assignment<T,18,4,Dynamic>(4, 3);
|
||||
dense_storage_assignment<T,18,Dynamic,3>(4, 3);
|
||||
|
||||
// Dynamic Storage.
|
||||
dense_storage_swap<T,Dynamic,Dynamic,Dynamic>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,Dynamic,Dynamic,Dynamic>(4, 3, 2, 1);
|
||||
dense_storage_swap<T,Dynamic,Dynamic,Dynamic>(2, 1, 4, 3);
|
||||
dense_storage_swap<T,Dynamic,Dynamic,3>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,Dynamic,Dynamic,3>(4, 3, 2, 3);
|
||||
dense_storage_swap<T,Dynamic,Dynamic,3>(2, 3, 4, 3);
|
||||
dense_storage_swap<T,Dynamic,4,Dynamic>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,Dynamic,4,Dynamic>(4, 3, 4, 1);
|
||||
dense_storage_swap<T,Dynamic,4,Dynamic>(4, 1, 4, 3);
|
||||
// Fixed Storage.
|
||||
dense_storage_swap<T,12,4,3>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,12,Dynamic,Dynamic>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,12,Dynamic,Dynamic>(4, 3, 2, 1);
|
||||
dense_storage_swap<T,12,Dynamic,Dynamic>(2, 1, 4, 3);
|
||||
dense_storage_swap<T,12,4,Dynamic>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,12,4,Dynamic>(4, 3, 4, 1);
|
||||
dense_storage_swap<T,12,4,Dynamic>(4, 1, 4, 3);
|
||||
dense_storage_swap<T,12,Dynamic,3>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,12,Dynamic,3>(4, 3, 2, 3);
|
||||
dense_storage_swap<T,12,Dynamic,3>(2, 3, 4, 3);
|
||||
// Fixed Storage with Uninitialized Elements.
|
||||
dense_storage_swap<T,18,Dynamic,Dynamic>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,18,Dynamic,Dynamic>(4, 3, 2, 1);
|
||||
dense_storage_swap<T,18,Dynamic,Dynamic>(2, 1, 4, 3);
|
||||
dense_storage_swap<T,18,4,Dynamic>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,18,4,Dynamic>(4, 3, 4, 1);
|
||||
dense_storage_swap<T,18,4,Dynamic>(4, 1, 4, 3);
|
||||
dense_storage_swap<T,18,Dynamic,3>(4, 3, 4, 3);
|
||||
dense_storage_swap<T,18,Dynamic,3>(4, 3, 2, 3);
|
||||
dense_storage_swap<T,18,Dynamic,3>(2, 3, 4, 3);
|
||||
|
||||
dense_storage_alignment<T,16,8>();
|
||||
dense_storage_alignment<T,16,16>();
|
||||
dense_storage_alignment<T,16,32>();
|
||||
dense_storage_alignment<T,16,64>();
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(dense_storage)
|
||||
{
|
||||
dense_storage_tests<int>();
|
||||
dense_storage_tests<float>();
|
||||
dense_storage_tests<SafeScalar<float> >();
|
||||
dense_storage_tests<AnnoyingScalar>();
|
||||
}
|
||||
66
libs/eigen/test/determinant.cpp
Normal file
66
libs/eigen/test/determinant.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
// 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) 2008 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>
|
||||
|
||||
template<typename MatrixType> void determinant(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Determinant.h
|
||||
*/
|
||||
Index size = m.rows();
|
||||
|
||||
MatrixType m1(size, size), m2(size, size);
|
||||
m1.setRandom();
|
||||
m2.setRandom();
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
Scalar x = internal::random<Scalar>();
|
||||
VERIFY_IS_APPROX(MatrixType::Identity(size, size).determinant(), Scalar(1));
|
||||
VERIFY_IS_APPROX((m1*m2).eval().determinant(), m1.determinant() * m2.determinant());
|
||||
if(size==1) return;
|
||||
Index i = internal::random<Index>(0, size-1);
|
||||
Index j;
|
||||
do {
|
||||
j = internal::random<Index>(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(numext::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);
|
||||
|
||||
// check empty matrix
|
||||
VERIFY_IS_APPROX(m2.block(0,0,0,0).determinant(), Scalar(1));
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(determinant)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
int s = 0;
|
||||
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>()) );
|
||||
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
|
||||
CALL_SUBTEST_6( determinant(MatrixXd(s, s)) );
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(s)
|
||||
}
|
||||
}
|
||||
105
libs/eigen/test/diagonal.cpp
Normal file
105
libs/eigen/test/diagonal.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-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 MatrixType> void diagonal(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
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();
|
||||
m2.diagonal()[0] *= 3;
|
||||
|
||||
if (rows>2)
|
||||
{
|
||||
enum {
|
||||
N1 = MatrixType::RowsAtCompileTime>2 ? 2 : 0,
|
||||
N2 = MatrixType::RowsAtCompileTime>1 ? -1 : 0
|
||||
};
|
||||
|
||||
// check sub/super diagonal
|
||||
if(MatrixType::SizeAtCompileTime!=Dynamic)
|
||||
{
|
||||
VERIFY(m1.template diagonal<N1>().RowsAtCompileTime == m1.diagonal(N1).size());
|
||||
VERIFY(m1.template diagonal<N2>().RowsAtCompileTime == m1.diagonal(N2).size());
|
||||
}
|
||||
|
||||
m2.template diagonal<N1>() = 2 * m1.template diagonal<N1>();
|
||||
VERIFY_IS_APPROX(m2.template diagonal<N1>(), static_cast<Scalar>(2) * m1.diagonal(N1));
|
||||
m2.template diagonal<N1>()[0] *= 3;
|
||||
VERIFY_IS_APPROX(m2.template diagonal<N1>()[0], static_cast<Scalar>(6) * m1.template diagonal<N1>()[0]);
|
||||
|
||||
|
||||
m2.template diagonal<N2>() = 2 * m1.template diagonal<N2>();
|
||||
m2.template diagonal<N2>()[0] *= 3;
|
||||
VERIFY_IS_APPROX(m2.template diagonal<N2>()[0], static_cast<Scalar>(6) * m1.template diagonal<N2>()[0]);
|
||||
|
||||
m2.diagonal(N1) = 2 * m1.diagonal(N1);
|
||||
VERIFY_IS_APPROX(m2.template diagonal<N1>(), static_cast<Scalar>(2) * m1.diagonal(N1));
|
||||
m2.diagonal(N1)[0] *= 3;
|
||||
VERIFY_IS_APPROX(m2.diagonal(N1)[0], static_cast<Scalar>(6) * m1.diagonal(N1)[0]);
|
||||
|
||||
m2.diagonal(N2) = 2 * m1.diagonal(N2);
|
||||
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);
|
||||
}
|
||||
|
||||
VERIFY( m1.diagonal( cols).size()==0 );
|
||||
VERIFY( m1.diagonal(-rows).size()==0 );
|
||||
}
|
||||
|
||||
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() );
|
||||
}
|
||||
|
||||
VERIFY_RAISES_ASSERT( m1.diagonal(cols+1) );
|
||||
VERIFY_RAISES_ASSERT( m1.diagonal(-(rows+1)) );
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(diagonal)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( diagonal(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_1( diagonal(Matrix<float, 4, 9>()) );
|
||||
CALL_SUBTEST_1( diagonal(Matrix<float, 7, 3>()) );
|
||||
CALL_SUBTEST_2( diagonal(Matrix4d()) );
|
||||
CALL_SUBTEST_2( diagonal(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_2( diagonal(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_2( diagonal(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
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))) );
|
||||
}
|
||||
}
|
||||
185
libs/eigen/test/diagonal_matrix_variadic_ctor.cpp
Normal file
185
libs/eigen/test/diagonal_matrix_variadic_ctor.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2019 David Tellenbach <david.tellenbach@tellnotes.org>
|
||||
//
|
||||
// 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 Scalar>
|
||||
void assertionTest()
|
||||
{
|
||||
typedef DiagonalMatrix<Scalar, 5> DiagMatrix5;
|
||||
typedef DiagonalMatrix<Scalar, 7> DiagMatrix7;
|
||||
typedef DiagonalMatrix<Scalar, Dynamic> DiagMatrixX;
|
||||
|
||||
Scalar raw[6];
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
raw[i] = internal::random<Scalar>();
|
||||
}
|
||||
|
||||
VERIFY_RAISES_ASSERT((DiagMatrix5{raw[0], raw[1], raw[2], raw[3]}));
|
||||
VERIFY_RAISES_ASSERT((DiagMatrix5{raw[0], raw[1], raw[3]}));
|
||||
VERIFY_RAISES_ASSERT((DiagMatrix7{raw[0], raw[1], raw[2], raw[3]}));
|
||||
|
||||
VERIFY_RAISES_ASSERT((DiagMatrixX {
|
||||
{raw[0], raw[1], raw[2]},
|
||||
{raw[3], raw[4], raw[5]}
|
||||
}));
|
||||
}
|
||||
|
||||
#define VERIFY_IMPLICIT_CONVERSION_3(DIAGTYPE, V0, V1, V2) \
|
||||
DIAGTYPE d(V0, V1, V2); \
|
||||
DIAGTYPE::DenseMatrixType Dense = d.toDenseMatrix(); \
|
||||
VERIFY_IS_APPROX(Dense(0, 0), (Scalar)V0); \
|
||||
VERIFY_IS_APPROX(Dense(1, 1), (Scalar)V1); \
|
||||
VERIFY_IS_APPROX(Dense(2, 2), (Scalar)V2);
|
||||
|
||||
#define VERIFY_IMPLICIT_CONVERSION_4(DIAGTYPE, V0, V1, V2, V3) \
|
||||
DIAGTYPE d(V0, V1, V2, V3); \
|
||||
DIAGTYPE::DenseMatrixType Dense = d.toDenseMatrix(); \
|
||||
VERIFY_IS_APPROX(Dense(0, 0), (Scalar)V0); \
|
||||
VERIFY_IS_APPROX(Dense(1, 1), (Scalar)V1); \
|
||||
VERIFY_IS_APPROX(Dense(2, 2), (Scalar)V2); \
|
||||
VERIFY_IS_APPROX(Dense(3, 3), (Scalar)V3);
|
||||
|
||||
#define VERIFY_IMPLICIT_CONVERSION_5(DIAGTYPE, V0, V1, V2, V3, V4) \
|
||||
DIAGTYPE d(V0, V1, V2, V3, V4); \
|
||||
DIAGTYPE::DenseMatrixType Dense = d.toDenseMatrix(); \
|
||||
VERIFY_IS_APPROX(Dense(0, 0), (Scalar)V0); \
|
||||
VERIFY_IS_APPROX(Dense(1, 1), (Scalar)V1); \
|
||||
VERIFY_IS_APPROX(Dense(2, 2), (Scalar)V2); \
|
||||
VERIFY_IS_APPROX(Dense(3, 3), (Scalar)V3); \
|
||||
VERIFY_IS_APPROX(Dense(4, 4), (Scalar)V4);
|
||||
|
||||
template<typename Scalar>
|
||||
void constructorTest()
|
||||
{
|
||||
typedef DiagonalMatrix<Scalar, 0> DiagonalMatrix0;
|
||||
typedef DiagonalMatrix<Scalar, 3> DiagonalMatrix3;
|
||||
typedef DiagonalMatrix<Scalar, 4> DiagonalMatrix4;
|
||||
typedef DiagonalMatrix<Scalar, Dynamic> DiagonalMatrixX;
|
||||
|
||||
Scalar raw[7];
|
||||
for (int k = 0; k < 7; ++k) raw[k] = internal::random<Scalar>();
|
||||
|
||||
// Fixed-sized matrices
|
||||
{
|
||||
DiagonalMatrix0 a {{}};
|
||||
VERIFY(a.rows() == 0);
|
||||
VERIFY(a.cols() == 0);
|
||||
typename DiagonalMatrix0::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
{
|
||||
DiagonalMatrix3 a {{raw[0], raw[1], raw[2]}};
|
||||
VERIFY(a.rows() == 3);
|
||||
VERIFY(a.cols() == 3);
|
||||
typename DiagonalMatrix3::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
{
|
||||
DiagonalMatrix4 a {{raw[0], raw[1], raw[2], raw[3]}};
|
||||
VERIFY(a.rows() == 4);
|
||||
VERIFY(a.cols() == 4);
|
||||
typename DiagonalMatrix4::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
|
||||
// dynamically sized matrices
|
||||
{
|
||||
DiagonalMatrixX a{{}};
|
||||
VERIFY(a.rows() == 0);
|
||||
VERIFY(a.rows() == 0);
|
||||
typename DiagonalMatrixX::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
{
|
||||
DiagonalMatrixX a{{raw[0], raw[1], raw[2], raw[3], raw[4], raw[5], raw[6]}};
|
||||
VERIFY(a.rows() == 7);
|
||||
VERIFY(a.rows() == 7);
|
||||
typename DiagonalMatrixX::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
void constructorTest<float>()
|
||||
{
|
||||
typedef float Scalar;
|
||||
|
||||
typedef DiagonalMatrix<Scalar, 0> DiagonalMatrix0;
|
||||
typedef DiagonalMatrix<Scalar, 3> DiagonalMatrix3;
|
||||
typedef DiagonalMatrix<Scalar, 4> DiagonalMatrix4;
|
||||
typedef DiagonalMatrix<Scalar, 5> DiagonalMatrix5;
|
||||
typedef DiagonalMatrix<Scalar, Dynamic> DiagonalMatrixX;
|
||||
|
||||
Scalar raw[7];
|
||||
for (int k = 0; k < 7; ++k) raw[k] = internal::random<Scalar>();
|
||||
|
||||
// Fixed-sized matrices
|
||||
{
|
||||
DiagonalMatrix0 a {{}};
|
||||
VERIFY(a.rows() == 0);
|
||||
VERIFY(a.cols() == 0);
|
||||
typename DiagonalMatrix0::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
{
|
||||
DiagonalMatrix3 a {{raw[0], raw[1], raw[2]}};
|
||||
VERIFY(a.rows() == 3);
|
||||
VERIFY(a.cols() == 3);
|
||||
typename DiagonalMatrix3::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
{
|
||||
DiagonalMatrix4 a {{raw[0], raw[1], raw[2], raw[3]}};
|
||||
VERIFY(a.rows() == 4);
|
||||
VERIFY(a.cols() == 4);
|
||||
typename DiagonalMatrix4::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
|
||||
// dynamically sized matrices
|
||||
{
|
||||
DiagonalMatrixX a{{}};
|
||||
VERIFY(a.rows() == 0);
|
||||
VERIFY(a.rows() == 0);
|
||||
typename DiagonalMatrixX::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
{
|
||||
DiagonalMatrixX a{{raw[0], raw[1], raw[2], raw[3], raw[4], raw[5], raw[6]}};
|
||||
VERIFY(a.rows() == 7);
|
||||
VERIFY(a.rows() == 7);
|
||||
typename DiagonalMatrixX::DenseMatrixType m = a.toDenseMatrix();
|
||||
for (Index k = 0; k < a.rows(); ++k) VERIFY(m(k, k) == raw[k]);
|
||||
}
|
||||
{ VERIFY_IMPLICIT_CONVERSION_3(DiagonalMatrix3, 1.2647, 2.56f, -3); }
|
||||
{ VERIFY_IMPLICIT_CONVERSION_4(DiagonalMatrix4, 1.2647, 2.56f, -3, 3.23f); }
|
||||
{ VERIFY_IMPLICIT_CONVERSION_5(DiagonalMatrix5, 1.2647, 2.56f, -3, 3.23f, 2); }
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(diagonal_matrix_variadic_ctor)
|
||||
{
|
||||
CALL_SUBTEST_1(assertionTest<unsigned char>());
|
||||
CALL_SUBTEST_1(assertionTest<float>());
|
||||
CALL_SUBTEST_1(assertionTest<Index>());
|
||||
CALL_SUBTEST_1(assertionTest<int>());
|
||||
CALL_SUBTEST_1(assertionTest<long int>());
|
||||
CALL_SUBTEST_1(assertionTest<std::ptrdiff_t>());
|
||||
CALL_SUBTEST_1(assertionTest<std::complex<double>>());
|
||||
|
||||
CALL_SUBTEST_2(constructorTest<unsigned char>());
|
||||
CALL_SUBTEST_2(constructorTest<float>());
|
||||
CALL_SUBTEST_2(constructorTest<Index>());
|
||||
CALL_SUBTEST_2(constructorTest<int>());
|
||||
CALL_SUBTEST_2(constructorTest<long int>());
|
||||
CALL_SUBTEST_2(constructorTest<std::ptrdiff_t>());
|
||||
CALL_SUBTEST_2(constructorTest<std::complex<double>>());
|
||||
}
|
||||
173
libs/eigen/test/diagonalmatrices.cpp
Normal file
173
libs/eigen/test/diagonalmatrices.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
// 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"
|
||||
using namespace std;
|
||||
template<typename MatrixType> void diagonalmatrices(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
|
||||
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;
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols);
|
||||
VectorType v1 = VectorType::Random(rows),
|
||||
v2 = VectorType::Random(rows);
|
||||
RowVectorType rv1 = RowVectorType::Random(cols),
|
||||
rv2 = RowVectorType::Random(cols);
|
||||
|
||||
LeftDiagonalMatrix ldm1(v1), ldm2(v2);
|
||||
RightDiagonalMatrix rdm1(rv1), rdm2(rv2);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
|
||||
SquareMatrixType sq_m1 (v1.asDiagonal());
|
||||
VERIFY_IS_APPROX(sq_m1, v1.asDiagonal().toDenseMatrix());
|
||||
sq_m1 = v1.asDiagonal();
|
||||
VERIFY_IS_APPROX(sq_m1, v1.asDiagonal().toDenseMatrix());
|
||||
SquareMatrixType sq_m2 = v1.asDiagonal();
|
||||
VERIFY_IS_APPROX(sq_m1, sq_m2);
|
||||
|
||||
ldm1 = v1.asDiagonal();
|
||||
LeftDiagonalMatrix ldm3(v1);
|
||||
VERIFY_IS_APPROX(ldm1.diagonal(), ldm3.diagonal());
|
||||
LeftDiagonalMatrix ldm4 = v1.asDiagonal();
|
||||
VERIFY_IS_APPROX(ldm1.diagonal(), ldm4.diagonal());
|
||||
|
||||
sq_m1.block(0,0,rows,rows) = ldm1;
|
||||
VERIFY_IS_APPROX(sq_m1, ldm1.toDenseMatrix());
|
||||
sq_m1.transpose() = ldm1;
|
||||
VERIFY_IS_APPROX(sq_m1, ldm1.toDenseMatrix());
|
||||
|
||||
Index i = internal::random<Index>(0, rows-1);
|
||||
Index j = internal::random<Index>(0, cols-1);
|
||||
|
||||
VERIFY_IS_APPROX( ((ldm1 * m1)(i,j)) , ldm1.diagonal()(i) * m1(i,j) );
|
||||
VERIFY_IS_APPROX( ((ldm1 * (m1+m2))(i,j)) , ldm1.diagonal()(i) * (m1+m2)(i,j) );
|
||||
VERIFY_IS_APPROX( ((m1 * rdm1)(i,j)) , rdm1.diagonal()(j) * m1(i,j) );
|
||||
VERIFY_IS_APPROX( ((v1.asDiagonal() * m1)(i,j)) , v1(i) * m1(i,j) );
|
||||
VERIFY_IS_APPROX( ((m1 * rv1.asDiagonal())(i,j)) , rv1(j) * m1(i,j) );
|
||||
VERIFY_IS_APPROX( (((v1+v2).asDiagonal() * m1)(i,j)) , (v1+v2)(i) * m1(i,j) );
|
||||
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);
|
||||
|
||||
big.block(i,j,rows,cols) = m1;
|
||||
big.block(i,j,rows,cols) = v1.asDiagonal() * big.block(i,j,rows,cols);
|
||||
|
||||
VERIFY_IS_APPROX((big.block(i,j,rows,cols)) , v1.asDiagonal() * m1 );
|
||||
|
||||
big.block(i,j,rows,cols) = m1;
|
||||
big.block(i,j,rows,cols) = big.block(i,j,rows,cols) * rv1.asDiagonal();
|
||||
VERIFY_IS_APPROX((big.block(i,j,rows,cols)) , m1 * rv1.asDiagonal() );
|
||||
|
||||
|
||||
// scalar multiple
|
||||
VERIFY_IS_APPROX(LeftDiagonalMatrix(ldm1*s1).diagonal(), ldm1.diagonal() * s1);
|
||||
VERIFY_IS_APPROX(LeftDiagonalMatrix(s1*ldm1).diagonal(), s1 * ldm1.diagonal());
|
||||
|
||||
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() );
|
||||
|
||||
sq_m1.setRandom();
|
||||
sq_m2 = v1.asDiagonal();
|
||||
sq_m2 = sq_m1 * sq_m2;
|
||||
VERIFY_IS_APPROX( (sq_m1*v1.asDiagonal()).col(i), sq_m2.col(i) );
|
||||
VERIFY_IS_APPROX( (sq_m1*v1.asDiagonal()).row(i), sq_m2.row(i) );
|
||||
|
||||
sq_m1 = v1.asDiagonal();
|
||||
sq_m2 = v2.asDiagonal();
|
||||
SquareMatrixType sq_m3 = v1.asDiagonal();
|
||||
VERIFY_IS_APPROX( sq_m3 = v1.asDiagonal() + v2.asDiagonal(), sq_m1 + sq_m2);
|
||||
VERIFY_IS_APPROX( sq_m3 = v1.asDiagonal() - v2.asDiagonal(), sq_m1 - sq_m2);
|
||||
VERIFY_IS_APPROX( sq_m3 = v1.asDiagonal() - 2*v2.asDiagonal() + v1.asDiagonal(), sq_m1 - 2*sq_m2 + sq_m1);
|
||||
}
|
||||
|
||||
template<typename MatrixType> void as_scalar_product(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic> DynMatrixType;
|
||||
typedef Matrix<Scalar, Dynamic, 1> DynVectorType;
|
||||
typedef Matrix<Scalar, 1, Dynamic> DynRowVectorType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index depth = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
|
||||
VectorType v1 = VectorType::Random(rows);
|
||||
DynVectorType dv1 = DynVectorType::Random(depth);
|
||||
DynRowVectorType drv1 = DynRowVectorType::Random(depth);
|
||||
DynMatrixType dm1 = dv1;
|
||||
DynMatrixType drm1 = drv1;
|
||||
|
||||
Scalar s = v1(0);
|
||||
|
||||
VERIFY_IS_APPROX( v1.asDiagonal() * drv1, s*drv1 );
|
||||
VERIFY_IS_APPROX( dv1 * v1.asDiagonal(), dv1*s );
|
||||
|
||||
VERIFY_IS_APPROX( v1.asDiagonal() * drm1, s*drm1 );
|
||||
VERIFY_IS_APPROX( dm1 * v1.asDiagonal(), dm1*s );
|
||||
}
|
||||
|
||||
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() );
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(diagonalmatrices)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( diagonalmatrices(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_1( as_scalar_product(Matrix<float, 1, 1>()) );
|
||||
|
||||
CALL_SUBTEST_2( diagonalmatrices(Matrix3f()) );
|
||||
CALL_SUBTEST_3( diagonalmatrices(Matrix<double,3,3,RowMajor>()) );
|
||||
CALL_SUBTEST_4( diagonalmatrices(Matrix4d()) );
|
||||
CALL_SUBTEST_5( diagonalmatrices(Matrix<float,4,4,RowMajor>()) );
|
||||
CALL_SUBTEST_6( diagonalmatrices(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( as_scalar_product(MatrixXcf(1,1)) );
|
||||
CALL_SUBTEST_7( diagonalmatrices(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
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_9( diagonalmatrices(MatrixXf(1,1)) );
|
||||
CALL_SUBTEST_9( as_scalar_product(MatrixXf(1,1)) );
|
||||
}
|
||||
CALL_SUBTEST_10( bug987<0>() );
|
||||
}
|
||||
62
libs/eigen/test/dontalign.cpp
Normal file
62
libs/eigen/test/dontalign.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011 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/.
|
||||
|
||||
#if defined EIGEN_TEST_PART_1 || defined EIGEN_TEST_PART_2 || defined EIGEN_TEST_PART_3 || defined EIGEN_TEST_PART_4
|
||||
#define EIGEN_DONT_ALIGN
|
||||
#elif defined EIGEN_TEST_PART_5 || defined EIGEN_TEST_PART_6 || defined EIGEN_TEST_PART_7 || defined EIGEN_TEST_PART_8
|
||||
#define EIGEN_DONT_ALIGN_STATICALLY
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/Dense>
|
||||
|
||||
template<typename MatrixType>
|
||||
void dontalign(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType a = MatrixType::Random(rows,cols);
|
||||
SquareMatrixType square = SquareMatrixType::Random(rows,rows);
|
||||
VectorType v = VectorType::Random(rows);
|
||||
|
||||
VERIFY_IS_APPROX(v, square * square.colPivHouseholderQr().solve(v));
|
||||
square = square.inverse().eval();
|
||||
a = square * a;
|
||||
square = square*square;
|
||||
v = square * v;
|
||||
v = a.adjoint() * v;
|
||||
VERIFY(square.determinant() != Scalar(0));
|
||||
|
||||
// bug 219: MapAligned() was giving an assert with EIGEN_DONT_ALIGN, because Map Flags were miscomputed
|
||||
Scalar* array = internal::aligned_new<Scalar>(rows);
|
||||
v = VectorType::MapAligned(array, rows);
|
||||
internal::aligned_delete(array, rows);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(dontalign)
|
||||
{
|
||||
#if defined EIGEN_TEST_PART_1 || defined EIGEN_TEST_PART_5
|
||||
dontalign(Matrix3d());
|
||||
dontalign(Matrix4f());
|
||||
#elif defined EIGEN_TEST_PART_2 || defined EIGEN_TEST_PART_6
|
||||
dontalign(Matrix3cd());
|
||||
dontalign(Matrix4cf());
|
||||
#elif defined EIGEN_TEST_PART_3 || defined EIGEN_TEST_PART_7
|
||||
dontalign(Matrix<float, 32, 32>());
|
||||
dontalign(Matrix<std::complex<float>, 32, 32>());
|
||||
#elif defined EIGEN_TEST_PART_4 || defined EIGEN_TEST_PART_8
|
||||
dontalign(MatrixXd(32, 32));
|
||||
dontalign(MatrixXcf(32, 32));
|
||||
#endif
|
||||
}
|
||||
177
libs/eigen/test/dynalloc.cpp
Normal file
177
libs/eigen/test/dynalloc.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 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"
|
||||
|
||||
#if EIGEN_MAX_ALIGN_BYTES>0
|
||||
#define ALIGNMENT EIGEN_MAX_ALIGN_BYTES
|
||||
#else
|
||||
#define ALIGNMENT 1
|
||||
#endif
|
||||
|
||||
typedef Matrix<float,16,1> Vector16f;
|
||||
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(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);
|
||||
}
|
||||
}
|
||||
|
||||
void check_aligned_malloc()
|
||||
{
|
||||
for(int i = ALIGNMENT; i < 1000; i++)
|
||||
{
|
||||
char *p = (char*)internal::aligned_malloc(i);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void check_aligned_new()
|
||||
{
|
||||
for(int i = ALIGNMENT; i < 1000; i++)
|
||||
{
|
||||
float *p = internal::aligned_new<float>(i);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void check_aligned_stack_alloc()
|
||||
{
|
||||
for(int i = ALIGNMENT; i < 400; i++)
|
||||
{
|
||||
ei_declare_aligned_stack_constructed_variable(float,p,i,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// test compilation with both a struct and a class...
|
||||
struct MyStruct
|
||||
{
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
char dummychar;
|
||||
Vector16f avec;
|
||||
};
|
||||
|
||||
class MyClassA
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
char dummychar;
|
||||
Vector16f avec;
|
||||
};
|
||||
|
||||
template<typename T> void check_dynaligned()
|
||||
{
|
||||
// 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 && (!EIGEN_HAS_CXX17_OVERALIGN)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(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_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>() );
|
||||
CALL_SUBTEST(check_dynaligned<Vector16f>() );
|
||||
}
|
||||
|
||||
{
|
||||
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(internal::UIntPtr(foo0->avec.data())%ALIGNMENT==0);
|
||||
MyClassA *fooA = new MyClassA(); VERIFY(internal::UIntPtr(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(internal::UIntPtr(foo0->avec.data())%ALIGNMENT==0);
|
||||
MyClassA *fooA = new MyClassA[N]; VERIFY(internal::UIntPtr(fooA->avec.data())%ALIGNMENT==0);
|
||||
delete[] foo0;
|
||||
delete[] fooA;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
65
libs/eigen/test/eigen2support.cpp
Normal file
65
libs/eigen/test/eigen2support.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 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 EIGEN2_SUPPORT
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void eigen2support(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>(),
|
||||
s2 = internal::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);
|
||||
|
||||
VERIFY_IS_EQUAL((m1.corner(TopLeft,1,1)), (m1.block(0,0,1,1)));
|
||||
VERIFY_IS_EQUAL((m1.template corner<1,1>(TopLeft)), (m1.template block<1,1>(0,0)));
|
||||
VERIFY_IS_EQUAL((m1.col(0).start(1)), (m1.col(0).segment(0,1)));
|
||||
VERIFY_IS_EQUAL((m1.col(0).template start<1>()), (m1.col(0).segment(0,1)));
|
||||
VERIFY_IS_EQUAL((m1.col(0).end(1)), (m1.col(0).segment(rows-1,1)));
|
||||
VERIFY_IS_EQUAL((m1.col(0).template end<1>()), (m1.col(0).segment(rows-1,1)));
|
||||
|
||||
using std::cos;
|
||||
using numext::real;
|
||||
using numext::abs2;
|
||||
VERIFY_IS_EQUAL(ei_cos(s1), cos(s1));
|
||||
VERIFY_IS_EQUAL(ei_real(s1), real(s1));
|
||||
VERIFY_IS_EQUAL(ei_abs2(s1), abs2(s1));
|
||||
|
||||
m1.minor(0,0);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(eigen2support)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( eigen2support(Matrix<double,1,1>()) );
|
||||
CALL_SUBTEST_2( eigen2support(MatrixXd(1,1)) );
|
||||
CALL_SUBTEST_4( eigen2support(Matrix3f()) );
|
||||
CALL_SUBTEST_5( eigen2support(Matrix4d()) );
|
||||
CALL_SUBTEST_2( eigen2support(MatrixXf(200,200)) );
|
||||
CALL_SUBTEST_6( eigen2support(MatrixXcd(100,100)) );
|
||||
}
|
||||
}
|
||||
176
libs/eigen/test/eigensolver_complex.cpp
Normal file
176
libs/eigen/test/eigensolver_complex.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
|
||||
//
|
||||
// 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 <limits>
|
||||
#include <Eigen/Eigenvalues>
|
||||
#include <Eigen/LU>
|
||||
|
||||
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 up to 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 VectorType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
VERIFY(vec1.cols() == 1);
|
||||
VERIFY(vec2.cols() == 1);
|
||||
VERIFY(vec1.rows() == vec2.rows());
|
||||
|
||||
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) );
|
||||
}
|
||||
|
||||
|
||||
template<typename MatrixType> void eigensolver(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
ComplexEigenSolver.h, and indirectly ComplexSchur.h
|
||||
*/
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
MatrixType a = MatrixType::Random(rows,cols);
|
||||
MatrixType symmA = a.adjoint() * a;
|
||||
|
||||
ComplexEigenSolver<MatrixType> ei0(symmA);
|
||||
VERIFY_IS_EQUAL(ei0.info(), Success);
|
||||
VERIFY_IS_APPROX(symmA * ei0.eigenvectors(), ei0.eigenvectors() * ei0.eigenvalues().asDiagonal());
|
||||
|
||||
ComplexEigenSolver<MatrixType> ei1(a);
|
||||
VERIFY_IS_EQUAL(ei1.info(), Success);
|
||||
VERIFY_IS_APPROX(a * ei1.eigenvectors(), ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
|
||||
// Note: If MatrixType is real then a.eigenvalues() uses EigenSolver and thus
|
||||
// another algorithm so results may differ slightly
|
||||
verify_is_approx_upto_permutation(a.eigenvalues(), ei1.eigenvalues());
|
||||
|
||||
ComplexEigenSolver<MatrixType> ei2;
|
||||
ei2.setMaxIterations(ComplexSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a);
|
||||
VERIFY_IS_EQUAL(ei2.info(), Success);
|
||||
VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors());
|
||||
VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues());
|
||||
if (rows > 2) {
|
||||
ei2.setMaxIterations(1).compute(a);
|
||||
VERIFY_IS_EQUAL(ei2.info(), NoConvergence);
|
||||
VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1);
|
||||
}
|
||||
|
||||
ComplexEigenSolver<MatrixType> eiNoEivecs(a, false);
|
||||
VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
|
||||
VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
|
||||
|
||||
// Regression test for issue #66
|
||||
MatrixType z = MatrixType::Zero(rows,cols);
|
||||
ComplexEigenSolver<MatrixType> eiz(z);
|
||||
VERIFY((eiz.eigenvalues().cwiseEqual(0)).all());
|
||||
|
||||
MatrixType id = MatrixType::Identity(rows, cols);
|
||||
VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(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)
|
||||
{
|
||||
ComplexEigenSolver<MatrixType> eig;
|
||||
VERIFY_RAISES_ASSERT(eig.eigenvectors());
|
||||
VERIFY_RAISES_ASSERT(eig.eigenvalues());
|
||||
|
||||
MatrixType a = MatrixType::Random(m.rows(),m.cols());
|
||||
eig.compute(a, false);
|
||||
VERIFY_RAISES_ASSERT(eig.eigenvectors());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(eigensolver_complex)
|
||||
{
|
||||
int s = 0;
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( eigensolver(Matrix4cf()) );
|
||||
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
|
||||
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);
|
||||
CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXcd(s,s)) );
|
||||
CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<std::complex<float>, 1, 1>()) );
|
||||
CALL_SUBTEST_4( eigensolver_verify_assert(Matrix3f()) );
|
||||
|
||||
// Test problem size constructors
|
||||
CALL_SUBTEST_5(ComplexEigenSolver<MatrixXf> tmp(s));
|
||||
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(s)
|
||||
}
|
||||
103
libs/eigen/test/eigensolver_generalized_real.cpp
Normal file
103
libs/eigen/test/eigensolver_generalized_real.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
GeneralizedEigenSolver.h
|
||||
*/
|
||||
Index rows = m.rows();
|
||||
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);
|
||||
MatrixType b = MatrixType::Random(rows,cols);
|
||||
MatrixType a1 = MatrixType::Random(rows,cols);
|
||||
MatrixType b1 = MatrixType::Random(rows,cols);
|
||||
MatrixType spdA = a.adjoint() * a + a1.adjoint() * a1;
|
||||
MatrixType spdB = b.adjoint() * b + b1.adjoint() * b1;
|
||||
|
||||
// lets compare to GeneralizedSelfAdjointEigenSolver
|
||||
{
|
||||
GeneralizedSelfAdjointEigenSolver<MatrixType> symmEig(spdA, spdB);
|
||||
GeneralizedEigenSolver<MatrixType> eig(spdA, spdB);
|
||||
|
||||
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());
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// check without eigenvectors
|
||||
{
|
||||
GeneralizedEigenSolver<MatrixType> eig1(spdA, spdB, true);
|
||||
GeneralizedEigenSolver<MatrixType> eig2(spdA, spdB, false);
|
||||
VERIFY_IS_APPROX(eig1.eigenvalues(), eig2.eigenvalues());
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(eigensolver_generalized_real)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
int s = 0;
|
||||
CALL_SUBTEST_1( generalized_eigensolver_real(Matrix4f()) );
|
||||
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
|
||||
CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(s,s)) );
|
||||
|
||||
// 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>()) );
|
||||
CALL_SUBTEST_4( generalized_eigensolver_real(Matrix2d()) );
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(s)
|
||||
}
|
||||
}
|
||||
247
libs/eigen/test/eigensolver_generic.cpp
Normal file
247
libs/eigen/test/eigensolver_generic.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
// 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) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
|
||||
//
|
||||
// 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 <limits>
|
||||
#include <Eigen/Eigenvalues>
|
||||
|
||||
template<typename EigType,typename MatType>
|
||||
void check_eigensolver_for_given_mat(const EigType &eig, const MatType& a)
|
||||
{
|
||||
typedef typename NumTraits<typename MatType::Scalar>::Real RealScalar;
|
||||
typedef Matrix<RealScalar, MatType::RowsAtCompileTime, 1> RealVectorType;
|
||||
typedef typename std::complex<RealScalar> Complex;
|
||||
Index n = a.rows();
|
||||
VERIFY_IS_EQUAL(eig.info(), Success);
|
||||
VERIFY_IS_APPROX(a * eig.pseudoEigenvectors(), eig.pseudoEigenvectors() * eig.pseudoEigenvalueMatrix());
|
||||
VERIFY_IS_APPROX(a.template cast<Complex>() * eig.eigenvectors(),
|
||||
eig.eigenvectors() * eig.eigenvalues().asDiagonal());
|
||||
VERIFY_IS_APPROX(eig.eigenvectors().colwise().norm(), RealVectorType::Ones(n).transpose());
|
||||
VERIFY_IS_APPROX(a.eigenvalues(), eig.eigenvalues());
|
||||
}
|
||||
|
||||
template<typename MatrixType> void eigensolver(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
EigenSolver.h
|
||||
*/
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef typename std::complex<RealScalar> Complex;
|
||||
|
||||
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_EQUAL(ei0.info(), Success);
|
||||
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);
|
||||
CALL_SUBTEST( check_eigensolver_for_given_mat(ei1,a) );
|
||||
|
||||
EigenSolver<MatrixType> ei2;
|
||||
ei2.setMaxIterations(RealSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a);
|
||||
VERIFY_IS_EQUAL(ei2.info(), Success);
|
||||
VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors());
|
||||
VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues());
|
||||
if (rows > 2) {
|
||||
ei2.setMaxIterations(1).compute(a);
|
||||
VERIFY_IS_EQUAL(ei2.info(), NoConvergence);
|
||||
VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1);
|
||||
}
|
||||
|
||||
EigenSolver<MatrixType> eiNoEivecs(a, false);
|
||||
VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
|
||||
VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
|
||||
VERIFY_IS_APPROX(ei1.pseudoEigenvalueMatrix(), eiNoEivecs.pseudoEigenvalueMatrix());
|
||||
|
||||
MatrixType id = MatrixType::Identity(rows, cols);
|
||||
VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));
|
||||
|
||||
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_NOT_EQUAL(eiNaN.info(), Success);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
EigenSolver<MatrixType> eig;
|
||||
VERIFY_RAISES_ASSERT(eig.eigenvectors());
|
||||
VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors());
|
||||
VERIFY_RAISES_ASSERT(eig.pseudoEigenvalueMatrix());
|
||||
VERIFY_RAISES_ASSERT(eig.eigenvalues());
|
||||
|
||||
MatrixType a = MatrixType::Random(m.rows(),m.cols());
|
||||
eig.compute(a, false);
|
||||
VERIFY_RAISES_ASSERT(eig.eigenvectors());
|
||||
VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors());
|
||||
}
|
||||
|
||||
|
||||
template<typename CoeffType>
|
||||
Matrix<typename CoeffType::Scalar,Dynamic,Dynamic>
|
||||
make_companion(const CoeffType& coeffs)
|
||||
{
|
||||
Index n = coeffs.size()-1;
|
||||
Matrix<typename CoeffType::Scalar,Dynamic,Dynamic> res(n,n);
|
||||
res.setZero();
|
||||
res.row(0) = -coeffs.tail(n) / coeffs(0);
|
||||
res.diagonal(-1).setOnes();
|
||||
return res;
|
||||
}
|
||||
|
||||
template<int>
|
||||
void eigensolver_generic_extra()
|
||||
{
|
||||
{
|
||||
// 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.);
|
||||
}
|
||||
|
||||
// regression test for bug 933
|
||||
{
|
||||
{
|
||||
VectorXd coeffs(5); coeffs << 1, -3, -175, -225, 2250;
|
||||
MatrixXd C = make_companion(coeffs);
|
||||
EigenSolver<MatrixXd> eig(C);
|
||||
CALL_SUBTEST( check_eigensolver_for_given_mat(eig,C) );
|
||||
}
|
||||
{
|
||||
// this test is tricky because it requires high accuracy in smallest eigenvalues
|
||||
VectorXd coeffs(5); coeffs << 6.154671e-15, -1.003870e-10, -9.819570e-01, 3.995715e+03, 2.211511e+08;
|
||||
MatrixXd C = make_companion(coeffs);
|
||||
EigenSolver<MatrixXd> eig(C);
|
||||
CALL_SUBTEST( check_eigensolver_for_given_mat(eig,C) );
|
||||
Index n = C.rows();
|
||||
for(Index i=0;i<n;++i)
|
||||
{
|
||||
typedef std::complex<double> Complex;
|
||||
MatrixXcd ac = C.cast<Complex>();
|
||||
ac.diagonal().array() -= eig.eigenvalues()(i);
|
||||
VectorXd sv = ac.jacobiSvd().singularValues();
|
||||
// comparing to sv(0) is not enough here to catch the "bug",
|
||||
// the hard-coded 1.0 is important!
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(sv(n-1), 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// regression test for bug 1557
|
||||
{
|
||||
// this test is interesting because it contains zeros on the diagonal.
|
||||
MatrixXd A_bug1557(3,3);
|
||||
A_bug1557 << 0, 0, 0, 1, 0, 0.5887907064808635127, 0, 1, 0;
|
||||
EigenSolver<MatrixXd> eig(A_bug1557);
|
||||
CALL_SUBTEST( check_eigensolver_for_given_mat(eig,A_bug1557) );
|
||||
}
|
||||
|
||||
// regression test for bug 1174
|
||||
{
|
||||
Index n = 12;
|
||||
MatrixXf A_bug1174(n,n);
|
||||
A_bug1174 << 262144, 0, 0, 262144, 786432, 0, 0, 0, 0, 0, 0, 786432,
|
||||
262144, 0, 0, 262144, 786432, 0, 0, 0, 0, 0, 0, 786432,
|
||||
262144, 0, 0, 262144, 786432, 0, 0, 0, 0, 0, 0, 786432,
|
||||
262144, 0, 0, 262144, 786432, 0, 0, 0, 0, 0, 0, 786432,
|
||||
0, 262144, 262144, 0, 0, 262144, 262144, 262144, 262144, 262144, 262144, 0,
|
||||
0, 262144, 262144, 0, 0, 262144, 262144, 262144, 262144, 262144, 262144, 0,
|
||||
0, 262144, 262144, 0, 0, 262144, 262144, 262144, 262144, 262144, 262144, 0,
|
||||
0, 262144, 262144, 0, 0, 262144, 262144, 262144, 262144, 262144, 262144, 0,
|
||||
0, 262144, 262144, 0, 0, 262144, 262144, 262144, 262144, 262144, 262144, 0,
|
||||
0, 262144, 262144, 0, 0, 262144, 262144, 262144, 262144, 262144, 262144, 0,
|
||||
0, 262144, 262144, 0, 0, 262144, 262144, 262144, 262144, 262144, 262144, 0,
|
||||
0, 262144, 262144, 0, 0, 262144, 262144, 262144, 262144, 262144, 262144, 0;
|
||||
EigenSolver<MatrixXf> eig(A_bug1174);
|
||||
CALL_SUBTEST( check_eigensolver_for_given_mat(eig,A_bug1174) );
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(eigensolver_generic)
|
||||
{
|
||||
int s = 0;
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
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)) );
|
||||
CALL_SUBTEST_2( eigensolver(MatrixXd(2,2)) );
|
||||
CALL_SUBTEST_3( eigensolver(Matrix<double,1,1>()) );
|
||||
CALL_SUBTEST_4( eigensolver(Matrix2d()) );
|
||||
}
|
||||
|
||||
CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4f()) );
|
||||
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
|
||||
CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXd(s,s)) );
|
||||
CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<double,1,1>()) );
|
||||
CALL_SUBTEST_4( eigensolver_verify_assert(Matrix2d()) );
|
||||
|
||||
// Test problem size constructors
|
||||
CALL_SUBTEST_5(EigenSolver<MatrixXf> tmp(s));
|
||||
|
||||
// regression test for bug 410
|
||||
CALL_SUBTEST_2(
|
||||
{
|
||||
MatrixXd A(1,1);
|
||||
A(0,0) = std::sqrt(-1.); // is Not-a-Number
|
||||
Eigen::EigenSolver<MatrixXd> solver(A);
|
||||
VERIFY_IS_EQUAL(solver.info(), NumericalIssue);
|
||||
}
|
||||
);
|
||||
|
||||
CALL_SUBTEST_2( eigensolver_generic_extra<0>() );
|
||||
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(s)
|
||||
}
|
||||
281
libs/eigen/test/eigensolver_selfadjoint.cpp
Normal file
281
libs/eigen/test/eigensolver_selfadjoint.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
// 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) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
|
||||
//
|
||||
// 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 "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)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
|
||||
*/
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
|
||||
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 symmC = symmA;
|
||||
|
||||
svd_fill_random(symmA,Symmetric);
|
||||
|
||||
symmA.template triangularView<StrictlyUpper>().setZero();
|
||||
symmC.template triangularView<StrictlyUpper>().setZero();
|
||||
|
||||
MatrixType b = MatrixType::Random(rows,cols);
|
||||
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);
|
||||
// generalized eigen pb
|
||||
GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmC, symmB);
|
||||
|
||||
SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false);
|
||||
VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success);
|
||||
VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues());
|
||||
|
||||
// generalized eigen problem Ax = lBx
|
||||
eiSymmGen.compute(symmC, symmB,Ax_lBx);
|
||||
VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
|
||||
VERIFY((symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox(
|
||||
symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
|
||||
|
||||
// generalized eigen problem BAx = lx
|
||||
eiSymmGen.compute(symmC, symmB,BAx_lx);
|
||||
VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
|
||||
VERIFY((symmB.template selfadjointView<Lower>() * (symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox(
|
||||
(eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
|
||||
|
||||
// generalized eigen problem ABx = lx
|
||||
eiSymmGen.compute(symmC, symmB,ABx_lx);
|
||||
VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
|
||||
VERIFY((symmC.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox(
|
||||
(eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
|
||||
|
||||
|
||||
eiSymm.compute(symmC);
|
||||
MatrixType sqrtSymmA = eiSymm.operatorSqrt();
|
||||
VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA);
|
||||
VERIFY_IS_APPROX(sqrtSymmA, symmC.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt());
|
||||
|
||||
MatrixType id = MatrixType::Identity(rows, cols);
|
||||
VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1));
|
||||
|
||||
SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized;
|
||||
VERIFY_RAISES_ASSERT(eiSymmUninitialized.info());
|
||||
VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues());
|
||||
VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
|
||||
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
|
||||
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());
|
||||
|
||||
eiSymmUninitialized.compute(symmA, false);
|
||||
VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
|
||||
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
|
||||
VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());
|
||||
|
||||
// test Tridiagonalization's methods
|
||||
Tridiagonalization<MatrixType> tridiag(symmC);
|
||||
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());
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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>()));
|
||||
CALL_SUBTEST_1( selfadjointeigensolver(Matrix<std::complex<double>, 1, 1>()));
|
||||
|
||||
// very important to test 3x3 and 2x2 matrices since we provide special paths for them
|
||||
CALL_SUBTEST_12( selfadjointeigensolver(Matrix2f()) );
|
||||
CALL_SUBTEST_12( selfadjointeigensolver(Matrix2d()) );
|
||||
CALL_SUBTEST_12( selfadjointeigensolver(Matrix2cd()) );
|
||||
CALL_SUBTEST_13( selfadjointeigensolver(Matrix3f()) );
|
||||
CALL_SUBTEST_13( selfadjointeigensolver(Matrix3d()) );
|
||||
CALL_SUBTEST_13( selfadjointeigensolver(Matrix3cd()) );
|
||||
CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
|
||||
CALL_SUBTEST_2( selfadjointeigensolver(Matrix4cd()) );
|
||||
|
||||
s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
|
||||
CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(s,s)) );
|
||||
CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(s,s)) );
|
||||
CALL_SUBTEST_5( selfadjointeigensolver(MatrixXcd(s,s)) );
|
||||
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)) );
|
||||
CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(2,2)) );
|
||||
CALL_SUBTEST_5( selfadjointeigensolver(MatrixXcd(1,1)) );
|
||||
CALL_SUBTEST_5( selfadjointeigensolver(MatrixXcd(2,2)) );
|
||||
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);
|
||||
CALL_SUBTEST_8(SelfAdjointEigenSolver<MatrixXf> tmp1(s));
|
||||
CALL_SUBTEST_8(Tridiagonalization<MatrixXf> tmp2(s));
|
||||
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(s)
|
||||
}
|
||||
|
||||
0
libs/eigen/test/evaluator_common.h
Normal file
0
libs/eigen/test/evaluator_common.h
Normal file
525
libs/eigen/test/evaluators.cpp
Normal file
525
libs/eigen/test/evaluators.cpp
Normal file
@@ -0,0 +1,525 @@
|
||||
|
||||
#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 Dst, template <typename> class StorageBase, typename Src, typename Func>
|
||||
EIGEN_DEVICE_FUNC void call_restricted_packet_assignment(const NoAlias<Dst,StorageBase>& dst, const Src& src, const Func& func)
|
||||
{
|
||||
call_restricted_packet_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());
|
||||
|
||||
EIGEN_DECLARE_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);
|
||||
}
|
||||
|
||||
// regression test for PR 544 and bug 1622 (introduced in #71609c4)
|
||||
{
|
||||
// test restricted_packet_assignment with an unaligned destination
|
||||
const size_t M = 2;
|
||||
const size_t K = 2;
|
||||
const size_t N = 5;
|
||||
float *destMem = new float[(M*N) + 1];
|
||||
float *dest = (internal::UIntPtr(destMem)%EIGEN_MAX_ALIGN_BYTES) == 0 ? destMem+1 : destMem;
|
||||
|
||||
const Matrix<float, Dynamic, Dynamic, RowMajor> a = Matrix<float, Dynamic, Dynamic, RowMajor>::Random(M, K);
|
||||
const Matrix<float, Dynamic, Dynamic, RowMajor> b = Matrix<float, Dynamic, Dynamic, RowMajor>::Random(K, N);
|
||||
|
||||
Map<Matrix<float, Dynamic, Dynamic, RowMajor> > z(dest, M, N);;
|
||||
Product<Matrix<float, Dynamic, Dynamic, RowMajor>, Matrix<float, Dynamic, Dynamic, RowMajor>, LazyProduct> tmp(a,b);
|
||||
internal::call_restricted_packet_assignment(z.noalias(), tmp.derived(), internal::assign_op<float, float>());
|
||||
|
||||
VERIFY_IS_APPROX(z, a*b);
|
||||
delete[] destMem;
|
||||
}
|
||||
}
|
||||
49
libs/eigen/test/exceptions.cpp
Normal file
49
libs/eigen/test/exceptions.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011 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/.
|
||||
|
||||
|
||||
// Various sanity tests with exceptions and non trivially copyable scalar type.
|
||||
// - no memory leak when a custom scalar type trow an exceptions
|
||||
// - todo: complete the list of tests!
|
||||
|
||||
#define EIGEN_STACK_ALLOCATION_LIMIT 100000000
|
||||
|
||||
#include "main.h"
|
||||
#include "AnnoyingScalar.h"
|
||||
|
||||
#define CHECK_MEMLEAK(OP) { \
|
||||
AnnoyingScalar::countdown = 100; \
|
||||
int before = AnnoyingScalar::instances; \
|
||||
bool exception_thrown = false; \
|
||||
try { OP; } \
|
||||
catch (my_exception) { \
|
||||
exception_thrown = true; \
|
||||
VERIFY(AnnoyingScalar::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \
|
||||
} \
|
||||
VERIFY( (AnnoyingScalar::dont_throw) || (exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)) ); \
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(exceptions)
|
||||
{
|
||||
typedef Eigen::Matrix<AnnoyingScalar,Dynamic,1> VectorType;
|
||||
typedef Eigen::Matrix<AnnoyingScalar,Dynamic,Dynamic> MatrixType;
|
||||
|
||||
{
|
||||
AnnoyingScalar::dont_throw = false;
|
||||
int n = 50;
|
||||
VectorType v0(n), v1(n);
|
||||
MatrixType m0(n,n), m1(n,n), m2(n,n);
|
||||
v0.setOnes(); v1.setOnes();
|
||||
m0.setOnes(); m1.setOnes(); m2.setOnes();
|
||||
CHECK_MEMLEAK(v0 = m0 * m1 * v1);
|
||||
CHECK_MEMLEAK(m2 = m0 * m1 * m2);
|
||||
CHECK_MEMLEAK((v0+v1).dot(v0+v1));
|
||||
}
|
||||
VERIFY(AnnoyingScalar::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP));
|
||||
}
|
||||
99
libs/eigen/test/fastmath.cpp
Normal file
99
libs/eigen/test/fastmath.cpp
Normal file
@@ -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
|
||||
{
|
||||
if( (std::isfinite)(m(3))) g_test_level=1; VERIFY( !(numext::isfinite)(m(3)) ); g_test_level=0;
|
||||
if( (std::isinf) (m(3))) g_test_level=1; VERIFY( !(numext::isinf)(m(3)) ); g_test_level=0;
|
||||
if(!(std::isnan) (m(3))) g_test_level=1; VERIFY( (numext::isnan)(m(3)) ); g_test_level=0;
|
||||
if( (std::isfinite)(m(3))) g_test_level=1; VERIFY( !m.allFinite() ); g_test_level=0;
|
||||
if(!(std::isnan) (m(3))) g_test_level=1; VERIFY( m.hasNaN() ); g_test_level=0;
|
||||
}
|
||||
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
|
||||
{
|
||||
if( (std::isfinite)(m(3))) g_test_level=1; VERIFY( !(numext::isfinite)(m(4)) ); g_test_level=0;
|
||||
if(!(std::isinf) (m(3))) g_test_level=1; VERIFY( (numext::isinf)(m(4)) ); g_test_level=0;
|
||||
if( (std::isnan) (m(3))) g_test_level=1; VERIFY( !(numext::isnan)(m(4)) ); g_test_level=0;
|
||||
if( (std::isfinite)(m(3))) g_test_level=1; VERIFY( !m.allFinite() ); g_test_level=0;
|
||||
if(!(std::isnan) (m(3))) g_test_level=1; VERIFY( m.hasNaN() ); g_test_level=0;
|
||||
}
|
||||
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
|
||||
{
|
||||
if(!(std::isfinite)(m(3))) g_test_level=1; VERIFY( (numext::isfinite)(m(3)) ); g_test_level=0;
|
||||
if( (std::isinf) (m(3))) g_test_level=1; VERIFY( !(numext::isinf)(m(3)) ); g_test_level=0;
|
||||
if( (std::isnan) (m(3))) g_test_level=1; VERIFY( !(numext::isnan)(m(3)) ); g_test_level=0;
|
||||
if( (std::isfinite)(m(3))) g_test_level=1; VERIFY( !m.allFinite() ); g_test_level=0;
|
||||
if( (std::isnan) (m(3))) g_test_level=1; VERIFY( !m.hasNaN() ); g_test_level=0;
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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);
|
||||
}
|
||||
51
libs/eigen/test/first_aligned.cpp
Normal file
51
libs/eigen/test/first_aligned.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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_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_default_aligned(array, size)) % packet_size) == 0);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
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_default_aligned(array, size) == size);
|
||||
}
|
||||
|
||||
struct some_non_vectorizable_type { float x; };
|
||||
|
||||
EIGEN_DECLARE_TEST(first_aligned)
|
||||
{
|
||||
EIGEN_ALIGN16 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_ALIGN16 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*)(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);
|
||||
|
||||
some_non_vectorizable_type array_nonvec[100];
|
||||
test_first_aligned_helper(array_nonvec, 100);
|
||||
test_none_aligned_helper(array_nonvec, 100);
|
||||
}
|
||||
531
libs/eigen/test/geo_alignedbox.cpp
Normal file
531
libs/eigen/test/geo_alignedbox.cpp
Normal file
@@ -0,0 +1,531 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 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/Geometry>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// NOTE the following workaround was needed on some 32 bits builds to kill extra precision of x87 registers.
|
||||
// It seems that it is not needed anymore, but let's keep it here, just in case...
|
||||
|
||||
template<typename T> EIGEN_DONT_INLINE
|
||||
void kill_extra_precision(T& /* x */) {
|
||||
// This one worked but triggered a warning:
|
||||
/* eigen_assert((void*)(&x) != (void*)0); */
|
||||
// An alternative could be:
|
||||
/* volatile T tmp = x; */
|
||||
/* x = tmp; */
|
||||
}
|
||||
|
||||
|
||||
template<typename BoxType> void alignedbox(const BoxType& box)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
AlignedBox.h
|
||||
*/
|
||||
typedef typename BoxType::Scalar Scalar;
|
||||
typedef NumTraits<Scalar> ScalarTraits;
|
||||
typedef typename ScalarTraits::Real RealScalar;
|
||||
typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
|
||||
|
||||
const Index dim = box.dim();
|
||||
|
||||
VectorType p0 = VectorType::Random(dim);
|
||||
VectorType p1 = VectorType::Random(dim);
|
||||
while( p1 == p0 ){
|
||||
p1 = VectorType::Random(dim); }
|
||||
RealScalar s1 = internal::random<RealScalar>(0,1);
|
||||
|
||||
BoxType b0(dim);
|
||||
BoxType b1(VectorType::Random(dim),VectorType::Random(dim));
|
||||
BoxType b2;
|
||||
|
||||
kill_extra_precision(b1);
|
||||
kill_extra_precision(p0);
|
||||
kill_extra_precision(p1);
|
||||
|
||||
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);
|
||||
BoxType *bp1 = new BoxType(dim);
|
||||
bp0->extend(*bp1);
|
||||
delete bp0;
|
||||
delete bp1;
|
||||
|
||||
// sampling
|
||||
for( int i=0; i<10; ++i )
|
||||
{
|
||||
VectorType r = b0.sample();
|
||||
VERIFY(b0.contains(r));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename BoxType> void alignedboxTranslatable(const BoxType& box)
|
||||
{
|
||||
typedef typename BoxType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
|
||||
typedef Transform<Scalar, BoxType::AmbientDimAtCompileTime, Isometry> IsometryTransform;
|
||||
typedef Transform<Scalar, BoxType::AmbientDimAtCompileTime, Affine> AffineTransform;
|
||||
|
||||
alignedbox(box);
|
||||
|
||||
const VectorType Ones = VectorType::Ones();
|
||||
const VectorType UnitX = VectorType::UnitX();
|
||||
const Index dim = box.dim();
|
||||
|
||||
// box((-1, -1, -1), (1, 1, 1))
|
||||
BoxType a(-Ones, Ones);
|
||||
|
||||
VERIFY_IS_APPROX(a.sizes(), Ones * Scalar(2));
|
||||
|
||||
BoxType b = a;
|
||||
VectorType translate = Ones;
|
||||
translate[0] = Scalar(2);
|
||||
b.translate(translate);
|
||||
// translate by (2, 1, 1) -> box((1, 0, 0), (3, 2, 2))
|
||||
|
||||
VERIFY_IS_APPROX(b.sizes(), Ones * Scalar(2));
|
||||
VERIFY_IS_APPROX((b.min)(), UnitX);
|
||||
VERIFY_IS_APPROX((b.max)(), Ones * Scalar(2) + UnitX);
|
||||
|
||||
// Test transform
|
||||
|
||||
IsometryTransform tf = IsometryTransform::Identity();
|
||||
tf.translation() = -translate;
|
||||
|
||||
BoxType c = b.transformed(tf);
|
||||
// translate by (-2, -1, -1) -> box((-1, -1, -1), (1, 1, 1))
|
||||
VERIFY_IS_APPROX(c.sizes(), a.sizes());
|
||||
VERIFY_IS_APPROX((c.min)(), (a.min)());
|
||||
VERIFY_IS_APPROX((c.max)(), (a.max)());
|
||||
|
||||
c.transform(tf);
|
||||
// translate by (-2, -1, -1) -> box((-3, -2, -2), (-1, 0, 0))
|
||||
VERIFY_IS_APPROX(c.sizes(), a.sizes());
|
||||
VERIFY_IS_APPROX((c.min)(), Ones * Scalar(-2) - UnitX);
|
||||
VERIFY_IS_APPROX((c.max)(), -UnitX);
|
||||
|
||||
// Scaling
|
||||
|
||||
AffineTransform atf = AffineTransform::Identity();
|
||||
atf.scale(Scalar(3));
|
||||
c.transform(atf);
|
||||
// scale by 3 -> box((-9, -6, -6), (-3, 0, 0))
|
||||
VERIFY_IS_APPROX(c.sizes(), Scalar(3) * a.sizes());
|
||||
VERIFY_IS_APPROX((c.min)(), Ones * Scalar(-6) - UnitX * Scalar(3));
|
||||
VERIFY_IS_APPROX((c.max)(), UnitX * Scalar(-3));
|
||||
|
||||
atf = AffineTransform::Identity();
|
||||
atf.scale(Scalar(-3));
|
||||
c.transform(atf);
|
||||
// scale by -3 -> box((27, 18, 18), (9, 0, 0))
|
||||
VERIFY_IS_APPROX(c.sizes(), Scalar(9) * a.sizes());
|
||||
VERIFY_IS_APPROX((c.min)(), UnitX * Scalar(9));
|
||||
VERIFY_IS_APPROX((c.max)(), Ones * Scalar(18) + UnitX * Scalar(9));
|
||||
|
||||
// Check identity transform within numerical precision.
|
||||
BoxType transformedC = c.transformed(IsometryTransform::Identity());
|
||||
VERIFY_IS_APPROX(transformedC, c);
|
||||
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
{
|
||||
VectorType minCorner;
|
||||
VectorType maxCorner;
|
||||
for (Index d = 0; d < dim; ++d)
|
||||
{
|
||||
minCorner[d] = internal::random<Scalar>(-10,10);
|
||||
maxCorner[d] = minCorner[d] + internal::random<Scalar>(0, 10);
|
||||
}
|
||||
|
||||
c = BoxType(minCorner, maxCorner);
|
||||
|
||||
translate = VectorType::Random();
|
||||
c.translate(translate);
|
||||
|
||||
VERIFY_IS_APPROX((c.min)(), minCorner + translate);
|
||||
VERIFY_IS_APPROX((c.max)(), maxCorner + translate);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Rotation>
|
||||
Rotation rotate2D(Scalar angle) {
|
||||
return Rotation2D<Scalar>(angle);
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Rotation>
|
||||
Rotation rotate2DIntegral(typename NumTraits<Scalar>::NonInteger angle) {
|
||||
typedef typename NumTraits<Scalar>::NonInteger NonInteger;
|
||||
return Rotation2D<NonInteger>(angle).toRotationMatrix().
|
||||
template cast<Scalar>();
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Rotation>
|
||||
Rotation rotate3DZAxis(Scalar angle) {
|
||||
return AngleAxis<Scalar>(angle, Matrix<Scalar, 3, 1>(0, 0, 1));
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Rotation>
|
||||
Rotation rotate3DZAxisIntegral(typename NumTraits<Scalar>::NonInteger angle) {
|
||||
typedef typename NumTraits<Scalar>::NonInteger NonInteger;
|
||||
return AngleAxis<NonInteger>(angle, Matrix<NonInteger, 3, 1>(0, 0, 1)).
|
||||
toRotationMatrix().template cast<Scalar>();
|
||||
}
|
||||
|
||||
template<typename Scalar, typename Rotation>
|
||||
Rotation rotate4DZWAxis(Scalar angle) {
|
||||
Rotation result = Matrix<Scalar, 4, 4>::Identity();
|
||||
result.block(0, 0, 3, 3) = rotate3DZAxis<Scalar, AngleAxisd>(angle).toRotationMatrix();
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename MatrixType>
|
||||
MatrixType randomRotationMatrix()
|
||||
{
|
||||
// algorithm from
|
||||
// https://www.isprs-ann-photogramm-remote-sens-spatial-inf-sci.net/III-7/103/2016/isprs-annals-III-7-103-2016.pdf
|
||||
const MatrixType rand = MatrixType::Random();
|
||||
const MatrixType q = rand.householderQr().householderQ();
|
||||
const JacobiSVD<MatrixType> svd = q.jacobiSvd(ComputeFullU | ComputeFullV);
|
||||
const typename MatrixType::Scalar det = (svd.matrixU() * svd.matrixV().transpose()).determinant();
|
||||
MatrixType diag = rand.Identity();
|
||||
diag(MatrixType::RowsAtCompileTime - 1, MatrixType::ColsAtCompileTime - 1) = det;
|
||||
const MatrixType rotation = svd.matrixU() * diag * svd.matrixV().transpose();
|
||||
return rotation;
|
||||
}
|
||||
|
||||
template <typename Scalar, int Dim>
|
||||
Matrix<Scalar, Dim, (1<<Dim)> boxGetCorners(const Matrix<Scalar, Dim, 1>& min_, const Matrix<Scalar, Dim, 1>& max_)
|
||||
{
|
||||
Matrix<Scalar, Dim, (1<<Dim) > result;
|
||||
for(Index i=0; i<(1<<Dim); ++i)
|
||||
{
|
||||
for(Index j=0; j<Dim; ++j)
|
||||
result(j,i) = (i & (1<<j)) ? min_(j) : max_(j);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename BoxType, typename Rotation> void alignedboxRotatable(
|
||||
const BoxType& box,
|
||||
Rotation (*rotate)(typename NumTraits<typename BoxType::Scalar>::NonInteger /*_angle*/))
|
||||
{
|
||||
alignedboxTranslatable(box);
|
||||
|
||||
typedef typename BoxType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::NonInteger NonInteger;
|
||||
typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
|
||||
typedef Transform<Scalar, BoxType::AmbientDimAtCompileTime, Isometry> IsometryTransform;
|
||||
typedef Transform<Scalar, BoxType::AmbientDimAtCompileTime, Affine> AffineTransform;
|
||||
|
||||
const VectorType Zero = VectorType::Zero();
|
||||
const VectorType Ones = VectorType::Ones();
|
||||
const VectorType UnitX = VectorType::UnitX();
|
||||
const VectorType UnitY = VectorType::UnitY();
|
||||
// this is vector (0, 0, -1, -1, -1, ...), i.e. with zeros at first and second dimensions
|
||||
const VectorType UnitZ = Ones - UnitX - UnitY;
|
||||
|
||||
// in this kind of comments the 3D case values will be illustrated
|
||||
// box((-1, -1, -1), (1, 1, 1))
|
||||
BoxType a(-Ones, Ones);
|
||||
|
||||
// to allow templating this test for both 2D and 3D cases, we always set all
|
||||
// but the first coordinate to the same value; so basically 3D case works as
|
||||
// if you were looking at the scene from top
|
||||
|
||||
VectorType minPoint = -2 * Ones;
|
||||
minPoint[0] = -3;
|
||||
VectorType maxPoint = Zero;
|
||||
maxPoint[0] = -1;
|
||||
BoxType c(minPoint, maxPoint);
|
||||
// box((-3, -2, -2), (-1, 0, 0))
|
||||
|
||||
IsometryTransform tf2 = IsometryTransform::Identity();
|
||||
// for some weird reason the following statement has to be put separate from
|
||||
// the following rotate call, otherwise precision problems arise...
|
||||
Rotation rot = rotate(NonInteger(EIGEN_PI));
|
||||
tf2.rotate(rot);
|
||||
|
||||
c.transform(tf2);
|
||||
// rotate by 180 deg around origin -> box((1, 0, -2), (3, 2, 0))
|
||||
|
||||
VERIFY_IS_APPROX(c.sizes(), a.sizes());
|
||||
VERIFY_IS_APPROX((c.min)(), UnitX - UnitZ * Scalar(2));
|
||||
VERIFY_IS_APPROX((c.max)(), UnitX * Scalar(3) + UnitY * Scalar(2));
|
||||
|
||||
rot = rotate(NonInteger(EIGEN_PI / 2));
|
||||
tf2.setIdentity();
|
||||
tf2.rotate(rot);
|
||||
|
||||
c.transform(tf2);
|
||||
// rotate by 90 deg around origin -> box((-2, 1, -2), (0, 3, 0))
|
||||
|
||||
VERIFY_IS_APPROX(c.sizes(), a.sizes());
|
||||
VERIFY_IS_APPROX((c.min)(), Ones * Scalar(-2) + UnitY * Scalar(3));
|
||||
VERIFY_IS_APPROX((c.max)(), UnitY * Scalar(3));
|
||||
|
||||
// box((-1, -1, -1), (1, 1, 1))
|
||||
AffineTransform atf = AffineTransform::Identity();
|
||||
atf.linearExt()(0, 1) = Scalar(1);
|
||||
c = BoxType(-Ones, Ones);
|
||||
c.transform(atf);
|
||||
// 45 deg shear in x direction -> box((-2, -1, -1), (2, 1, 1))
|
||||
|
||||
VERIFY_IS_APPROX(c.sizes(), Ones * Scalar(2) + UnitX * Scalar(2));
|
||||
VERIFY_IS_APPROX((c.min)(), -Ones - UnitX);
|
||||
VERIFY_IS_APPROX((c.max)(), Ones + UnitX);
|
||||
}
|
||||
|
||||
template<typename BoxType, typename Rotation> void alignedboxNonIntegralRotatable(
|
||||
const BoxType& box,
|
||||
Rotation (*rotate)(typename NumTraits<typename BoxType::Scalar>::NonInteger /*_angle*/))
|
||||
{
|
||||
alignedboxRotatable(box, rotate);
|
||||
|
||||
typedef typename BoxType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::NonInteger NonInteger;
|
||||
enum { Dim = BoxType::AmbientDimAtCompileTime };
|
||||
typedef Matrix<Scalar, Dim, 1> VectorType;
|
||||
typedef Matrix<Scalar, Dim, (1 << Dim)> CornersType;
|
||||
typedef Transform<Scalar, Dim, Isometry> IsometryTransform;
|
||||
typedef Transform<Scalar, Dim, Affine> AffineTransform;
|
||||
|
||||
const Index dim = box.dim();
|
||||
const VectorType Zero = VectorType::Zero();
|
||||
const VectorType Ones = VectorType::Ones();
|
||||
|
||||
VectorType minPoint = -2 * Ones;
|
||||
minPoint[1] = 1;
|
||||
VectorType maxPoint = Zero;
|
||||
maxPoint[1] = 3;
|
||||
BoxType c(minPoint, maxPoint);
|
||||
// ((-2, 1, -2), (0, 3, 0))
|
||||
|
||||
VectorType cornerBL = (c.min)();
|
||||
VectorType cornerTR = (c.max)();
|
||||
VectorType cornerBR = (c.min)(); cornerBR[0] = cornerTR[0];
|
||||
VectorType cornerTL = (c.max)(); cornerTL[0] = cornerBL[0];
|
||||
|
||||
NonInteger angle = NonInteger(EIGEN_PI/3);
|
||||
Rotation rot = rotate(angle);
|
||||
IsometryTransform tf2;
|
||||
tf2.setIdentity();
|
||||
tf2.rotate(rot);
|
||||
|
||||
c.transform(tf2);
|
||||
// rotate by 60 deg -> box((-3.59, -1.23, -2), (-0.86, 1.5, 0))
|
||||
|
||||
cornerBL = tf2 * cornerBL;
|
||||
cornerBR = tf2 * cornerBR;
|
||||
cornerTL = tf2 * cornerTL;
|
||||
cornerTR = tf2 * cornerTR;
|
||||
|
||||
VectorType minCorner = Ones * Scalar(-2);
|
||||
VectorType maxCorner = Zero;
|
||||
minCorner[0] = (min)((min)(cornerBL[0], cornerBR[0]), (min)(cornerTL[0], cornerTR[0]));
|
||||
maxCorner[0] = (max)((max)(cornerBL[0], cornerBR[0]), (max)(cornerTL[0], cornerTR[0]));
|
||||
minCorner[1] = (min)((min)(cornerBL[1], cornerBR[1]), (min)(cornerTL[1], cornerTR[1]));
|
||||
maxCorner[1] = (max)((max)(cornerBL[1], cornerBR[1]), (max)(cornerTL[1], cornerTR[1]));
|
||||
|
||||
for (Index d = 2; d < dim; ++d)
|
||||
VERIFY_IS_APPROX(c.sizes()[d], Scalar(2));
|
||||
|
||||
VERIFY_IS_APPROX((c.min)(), minCorner);
|
||||
VERIFY_IS_APPROX((c.max)(), maxCorner);
|
||||
|
||||
VectorType minCornerValue = Ones * Scalar(-2);
|
||||
VectorType maxCornerValue = Zero;
|
||||
minCornerValue[0] = Scalar(Scalar(-sqrt(2*2 + 3*3)) * Scalar(cos(Scalar(atan(2.0/3.0)) - angle/2)));
|
||||
minCornerValue[1] = Scalar(Scalar(-sqrt(1*1 + 2*2)) * Scalar(sin(Scalar(atan(2.0/1.0)) - angle/2)));
|
||||
maxCornerValue[0] = Scalar(-sin(angle));
|
||||
maxCornerValue[1] = Scalar(3 * cos(angle));
|
||||
VERIFY_IS_APPROX((c.min)(), minCornerValue);
|
||||
VERIFY_IS_APPROX((c.max)(), maxCornerValue);
|
||||
|
||||
// randomized test - translate and rotate the box and compare to a box made of transformed vertices
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
{
|
||||
for (Index d = 0; d < dim; ++d)
|
||||
{
|
||||
minCorner[d] = internal::random<Scalar>(-10,10);
|
||||
maxCorner[d] = minCorner[d] + internal::random<Scalar>(0, 10);
|
||||
}
|
||||
|
||||
c = BoxType(minCorner, maxCorner);
|
||||
|
||||
CornersType corners = boxGetCorners(minCorner, maxCorner);
|
||||
|
||||
typename AffineTransform::LinearMatrixType rotation =
|
||||
randomRotationMatrix<typename AffineTransform::LinearMatrixType>();
|
||||
|
||||
tf2.setIdentity();
|
||||
tf2.rotate(rotation);
|
||||
tf2.translate(VectorType::Random());
|
||||
|
||||
c.transform(tf2);
|
||||
corners = tf2 * corners;
|
||||
|
||||
minCorner = corners.rowwise().minCoeff();
|
||||
maxCorner = corners.rowwise().maxCoeff();
|
||||
|
||||
VERIFY_IS_APPROX((c.min)(), minCorner);
|
||||
VERIFY_IS_APPROX((c.max)(), maxCorner);
|
||||
}
|
||||
|
||||
// randomized test - transform the box with a random affine matrix and compare to a box made of transformed vertices
|
||||
for (size_t i = 0; i < 10; ++i)
|
||||
{
|
||||
for (Index d = 0; d < dim; ++d)
|
||||
{
|
||||
minCorner[d] = internal::random<Scalar>(-10,10);
|
||||
maxCorner[d] = minCorner[d] + internal::random<Scalar>(0, 10);
|
||||
}
|
||||
|
||||
c = BoxType(minCorner, maxCorner);
|
||||
|
||||
CornersType corners = boxGetCorners(minCorner, maxCorner);
|
||||
|
||||
AffineTransform atf = AffineTransform::Identity();
|
||||
atf.linearExt() = AffineTransform::LinearPart::Random();
|
||||
atf.translate(VectorType::Random());
|
||||
|
||||
c.transform(atf);
|
||||
corners = atf * corners;
|
||||
|
||||
minCorner = corners.rowwise().minCoeff();
|
||||
maxCorner = corners.rowwise().maxCoeff();
|
||||
|
||||
VERIFY_IS_APPROX((c.min)(), minCorner);
|
||||
VERIFY_IS_APPROX((c.max)(), maxCorner);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename BoxType>
|
||||
void alignedboxCastTests(const BoxType& box)
|
||||
{
|
||||
// casting
|
||||
typedef typename BoxType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
|
||||
|
||||
const Index dim = box.dim();
|
||||
|
||||
VectorType p0 = VectorType::Random(dim);
|
||||
VectorType p1 = VectorType::Random(dim);
|
||||
|
||||
BoxType b0(dim);
|
||||
|
||||
b0.extend(p0);
|
||||
b0.extend(p1);
|
||||
|
||||
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 specificTest1()
|
||||
{
|
||||
Vector2f m; m << -1.0f, -2.0f;
|
||||
Vector2f M; M << 1.0f, 5.0f;
|
||||
|
||||
typedef AlignedBox2f BoxType;
|
||||
BoxType box( m, M );
|
||||
|
||||
Vector2f sides = M-m;
|
||||
VERIFY_IS_APPROX(sides, box.sizes() );
|
||||
VERIFY_IS_APPROX(sides[1], box.sizes()[1] );
|
||||
VERIFY_IS_APPROX(sides[1], box.sizes().maxCoeff() );
|
||||
VERIFY_IS_APPROX(sides[0], box.sizes().minCoeff() );
|
||||
|
||||
VERIFY_IS_APPROX( 14.0f, box.volume() );
|
||||
VERIFY_IS_APPROX( 53.0f, box.diagonal().squaredNorm() );
|
||||
VERIFY_IS_APPROX( std::sqrt( 53.0f ), box.diagonal().norm() );
|
||||
|
||||
VERIFY_IS_APPROX( m, box.corner( BoxType::BottomLeft ) );
|
||||
VERIFY_IS_APPROX( M, box.corner( BoxType::TopRight ) );
|
||||
Vector2f bottomRight; bottomRight << M[0], m[1];
|
||||
Vector2f topLeft; topLeft << m[0], M[1];
|
||||
VERIFY_IS_APPROX( bottomRight, box.corner( BoxType::BottomRight ) );
|
||||
VERIFY_IS_APPROX( topLeft, box.corner( BoxType::TopLeft ) );
|
||||
}
|
||||
|
||||
|
||||
void specificTest2()
|
||||
{
|
||||
Vector3i m; m << -1, -2, 0;
|
||||
Vector3i M; M << 1, 5, 3;
|
||||
|
||||
typedef AlignedBox3i BoxType;
|
||||
BoxType box( m, M );
|
||||
|
||||
Vector3i sides = M-m;
|
||||
VERIFY_IS_APPROX(sides, box.sizes() );
|
||||
VERIFY_IS_APPROX(sides[1], box.sizes()[1] );
|
||||
VERIFY_IS_APPROX(sides[1], box.sizes().maxCoeff() );
|
||||
VERIFY_IS_APPROX(sides[0], box.sizes().minCoeff() );
|
||||
|
||||
VERIFY_IS_APPROX( 42, box.volume() );
|
||||
VERIFY_IS_APPROX( 62, box.diagonal().squaredNorm() );
|
||||
|
||||
VERIFY_IS_APPROX( m, box.corner( BoxType::BottomLeftFloor ) );
|
||||
VERIFY_IS_APPROX( M, box.corner( BoxType::TopRightCeil ) );
|
||||
Vector3i bottomRightFloor; bottomRightFloor << M[0], m[1], m[2];
|
||||
Vector3i topLeftFloor; topLeftFloor << m[0], M[1], m[2];
|
||||
VERIFY_IS_APPROX( bottomRightFloor, box.corner( BoxType::BottomRightFloor ) );
|
||||
VERIFY_IS_APPROX( topLeftFloor, box.corner( BoxType::TopLeftFloor ) );
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DECLARE_TEST(geo_alignedbox)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++)
|
||||
{
|
||||
CALL_SUBTEST_1( (alignedboxNonIntegralRotatable<AlignedBox2f, Rotation2Df>(AlignedBox2f(), &rotate2D)) );
|
||||
CALL_SUBTEST_2( alignedboxCastTests(AlignedBox2f()) );
|
||||
|
||||
CALL_SUBTEST_3( (alignedboxNonIntegralRotatable<AlignedBox3f, AngleAxisf>(AlignedBox3f(), &rotate3DZAxis)) );
|
||||
CALL_SUBTEST_4( alignedboxCastTests(AlignedBox3f()) );
|
||||
|
||||
CALL_SUBTEST_5( (alignedboxNonIntegralRotatable<AlignedBox4d, Matrix4d>(AlignedBox4d(), &rotate4DZWAxis)) );
|
||||
CALL_SUBTEST_6( alignedboxCastTests(AlignedBox4d()) );
|
||||
|
||||
CALL_SUBTEST_7( alignedboxTranslatable(AlignedBox1d()) );
|
||||
CALL_SUBTEST_8( alignedboxCastTests(AlignedBox1d()) );
|
||||
|
||||
CALL_SUBTEST_9( alignedboxTranslatable(AlignedBox1i()) );
|
||||
CALL_SUBTEST_10( (alignedboxRotatable<AlignedBox2i, Matrix2i>(AlignedBox2i(), &rotate2DIntegral<int, Matrix2i>)) );
|
||||
CALL_SUBTEST_11( (alignedboxRotatable<AlignedBox3i, Matrix3i>(AlignedBox3i(), &rotate3DZAxisIntegral<int, Matrix3i>)) );
|
||||
|
||||
CALL_SUBTEST_14( alignedbox(AlignedBox<double,Dynamic>(4)) );
|
||||
}
|
||||
CALL_SUBTEST_12( specificTest1() );
|
||||
CALL_SUBTEST_13( specificTest2() );
|
||||
}
|
||||
112
libs/eigen/test/geo_eulerangles.cpp
Normal file
112
libs/eigen/test/geo_eulerangles.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2012 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/Geometry>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/SVD>
|
||||
|
||||
|
||||
template<typename Scalar>
|
||||
void verify_euler(const Matrix<Scalar,3,1>& ea, int i, int j, int k)
|
||||
{
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef AngleAxis<Scalar> AngleAxisx;
|
||||
using std::abs;
|
||||
Matrix3 m(AngleAxisx(ea[0], Vector3::Unit(i)) * AngleAxisx(ea[1], Vector3::Unit(j)) * AngleAxisx(ea[2], Vector3::Unit(k)));
|
||||
Vector3 eabis = m.eulerAngles(i, j, k);
|
||||
Matrix3 mbis(AngleAxisx(eabis[0], Vector3::Unit(i)) * AngleAxisx(eabis[1], Vector3::Unit(j)) * AngleAxisx(eabis[2], Vector3::Unit(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(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(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)
|
||||
{
|
||||
verify_euler(ea, 0,1,2);
|
||||
verify_euler(ea, 0,1,0);
|
||||
verify_euler(ea, 0,2,1);
|
||||
verify_euler(ea, 0,2,0);
|
||||
|
||||
verify_euler(ea, 1,2,0);
|
||||
verify_euler(ea, 1,2,1);
|
||||
verify_euler(ea, 1,0,2);
|
||||
verify_euler(ea, 1,0,1);
|
||||
|
||||
verify_euler(ea, 2,0,1);
|
||||
verify_euler(ea, 2,0,2);
|
||||
verify_euler(ea, 2,1,0);
|
||||
verify_euler(ea, 2,1,2);
|
||||
}
|
||||
|
||||
template<typename Scalar> void eulerangles()
|
||||
{
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef Array<Scalar,3,1> Array3;
|
||||
typedef Quaternion<Scalar> Quaternionx;
|
||||
typedef AngleAxis<Scalar> AngleAxisx;
|
||||
|
||||
Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
|
||||
Quaternionx q1;
|
||||
q1 = AngleAxisx(a, Vector3::Random().normalized());
|
||||
Matrix3 m;
|
||||
m = q1;
|
||||
|
||||
Vector3 ea = m.eulerAngles(0,1,2);
|
||||
check_all_var(ea);
|
||||
ea = m.eulerAngles(0,1,0);
|
||||
check_all_var(ea);
|
||||
|
||||
// Check with purely random Quaternion:
|
||||
q1.coeffs() = Quaternionx::Coefficients::Random().normalized();
|
||||
m = q1;
|
||||
ea = m.eulerAngles(0,1,2);
|
||||
check_all_var(ea);
|
||||
ea = m.eulerAngles(0,1,0);
|
||||
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(EIGEN_PI)*Array3(0.5,1,1);
|
||||
check_all_var(ea);
|
||||
|
||||
ea[2] = ea[0] = internal::random<Scalar>(0,Scalar(EIGEN_PI));
|
||||
check_all_var(ea);
|
||||
|
||||
ea[0] = ea[1] = internal::random<Scalar>(0,Scalar(EIGEN_PI));
|
||||
check_all_var(ea);
|
||||
|
||||
ea[1] = 0;
|
||||
check_all_var(ea);
|
||||
|
||||
ea.head(2).setZero();
|
||||
check_all_var(ea);
|
||||
|
||||
ea.setZero();
|
||||
check_all_var(ea);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(geo_eulerangles)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( eulerangles<float>() );
|
||||
CALL_SUBTEST_2( eulerangles<double>() );
|
||||
}
|
||||
}
|
||||
125
libs/eigen/test/geo_homogeneous.cpp
Normal file
125
libs/eigen/test/geo_homogeneous.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 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/Geometry>
|
||||
|
||||
template<typename Scalar,int Size> void homogeneous(void)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Homogeneous.h
|
||||
*/
|
||||
|
||||
typedef Matrix<Scalar,Size,Size> MatrixType;
|
||||
typedef Matrix<Scalar,Size,1, ColMajor> VectorType;
|
||||
|
||||
typedef Matrix<Scalar,Size+1,Size> HMatrixType;
|
||||
typedef Matrix<Scalar,Size+1,1> HVectorType;
|
||||
|
||||
typedef Matrix<Scalar,Size,Size+1> T1MatrixType;
|
||||
typedef Matrix<Scalar,Size+1,Size+1> T2MatrixType;
|
||||
typedef Matrix<Scalar,Size+1,Size> T3MatrixType;
|
||||
|
||||
VectorType v0 = VectorType::Random(),
|
||||
ones = VectorType::Ones();
|
||||
|
||||
HVectorType hv0 = HVectorType::Random();
|
||||
|
||||
MatrixType m0 = MatrixType::Random();
|
||||
|
||||
HMatrixType hm0 = HMatrixType::Random();
|
||||
|
||||
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);
|
||||
VERIFY_IS_APPROX(m0, hm0.colwise().hnormalized());
|
||||
hm0.row(Size-1).setRandom();
|
||||
for(int j=0; j<Size; ++j)
|
||||
m0.col(j) = hm0.col(j).head(Size) / hm0(Size,j);
|
||||
VERIFY_IS_APPROX(m0, hm0.colwise().hnormalized());
|
||||
|
||||
T1MatrixType t1 = T1MatrixType::Random();
|
||||
VERIFY_IS_APPROX(t1 * (v0.homogeneous().eval()), t1 * v0.homogeneous());
|
||||
VERIFY_IS_APPROX(t1 * (m0.colwise().homogeneous().eval()), t1 * m0.colwise().homogeneous());
|
||||
|
||||
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);
|
||||
VERIFY_IS_APPROX((m0.transpose().rowwise().homogeneous().eval()) * t2,
|
||||
m0.transpose().rowwise().homogeneous() * t2);
|
||||
|
||||
T3MatrixType t3 = T3MatrixType::Random();
|
||||
VERIFY_IS_APPROX((v0.transpose().rowwise().homogeneous().eval()) * t3,
|
||||
v0.transpose().rowwise().homogeneous() * t3);
|
||||
VERIFY_IS_APPROX((m0.transpose().rowwise().homogeneous().eval()) * t3,
|
||||
m0.transpose().rowwise().homogeneous() * t3);
|
||||
|
||||
// test product with a Transform object
|
||||
Transform<Scalar, Size, Affine> aff;
|
||||
Transform<Scalar, Size, AffineCompact> caff;
|
||||
Transform<Scalar, Size, Projective> proj;
|
||||
Matrix<Scalar, Size, Dynamic> pts;
|
||||
Matrix<Scalar, Size+1, Dynamic> pts1, pts2;
|
||||
|
||||
aff.affine().setRandom();
|
||||
proj = caff = aff;
|
||||
pts.setRandom(Size,internal::random<int>(1,20));
|
||||
|
||||
pts1 = pts.colwise().homogeneous();
|
||||
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);
|
||||
|
||||
pts2 = pts1;
|
||||
pts2.row(Size).setRandom();
|
||||
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) );
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(geo_homogeneous)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1(( homogeneous<float,1>() ));
|
||||
CALL_SUBTEST_2(( homogeneous<double,3>() ));
|
||||
CALL_SUBTEST_3(( homogeneous<double,8>() ));
|
||||
}
|
||||
}
|
||||
192
libs/eigen/test/geo_hyperplane.cpp
Normal file
192
libs/eigen/test/geo_hyperplane.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
// 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 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
|
||||
*/
|
||||
using std::abs;
|
||||
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;
|
||||
|
||||
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 = internal::random<Scalar>();
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
|
||||
VERIFY_IS_APPROX( n1.dot(n1), Scalar(1) );
|
||||
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( pl0.absDistance(p0), Scalar(1) );
|
||||
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) );
|
||||
|
||||
// transform
|
||||
if (!NumTraits<Scalar>::IsComplex)
|
||||
{
|
||||
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) );
|
||||
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) );
|
||||
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) );
|
||||
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
|
||||
const int Dim = HyperplaneType::AmbientDimAtCompileTime;
|
||||
typedef typename GetDifferentType<Scalar>::type OtherScalar;
|
||||
Hyperplane<OtherScalar,Dim,Options> hp1f = pl1.template cast<OtherScalar>();
|
||||
VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),pl1);
|
||||
Hyperplane<Scalar,Dim,Options> hp1d = pl1.template cast<Scalar>();
|
||||
VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),pl1);
|
||||
}
|
||||
|
||||
template<typename Scalar> void lines()
|
||||
{
|
||||
using std::abs;
|
||||
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 = internal::random<Scalar>();
|
||||
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);
|
||||
|
||||
// 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"
|
||||
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 crash if we don't name this variable.
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar> void planes()
|
||||
{
|
||||
using std::abs;
|
||||
typedef Hyperplane<Scalar, 3> Plane;
|
||||
typedef Matrix<Scalar,3,1> Vector;
|
||||
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
Vector v0 = Vector::Random();
|
||||
Vector v1(v0), v2(v0);
|
||||
if(internal::random<double>(0,1)>0.25)
|
||||
v1 += Vector::Random();
|
||||
if(internal::random<double>(0,1)>0.25)
|
||||
v2 += v1 * std::pow(internal::random<Scalar>(0,1),internal::random<int>(1,16));
|
||||
if(internal::random<double>(0,1)>0.25)
|
||||
v2 += Vector::Random() * std::pow(internal::random<Scalar>(0,1),internal::random<int>(1,16));
|
||||
|
||||
Plane p0 = Plane::Through(v0, v1, v2);
|
||||
|
||||
VERIFY_IS_APPROX(p0.normal().norm(), Scalar(1));
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v0), Scalar(1));
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v1), Scalar(1));
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v2), Scalar(1));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar> void hyperplane_alignment()
|
||||
{
|
||||
typedef Hyperplane<Scalar,3,AutoAlign> Plane3a;
|
||||
typedef Hyperplane<Scalar,3,DontAlign> Plane3u;
|
||||
|
||||
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;
|
||||
Plane3u *p2 = ::new(reinterpret_cast<void*>(array2)) Plane3u;
|
||||
Plane3u *p3 = ::new(reinterpret_cast<void*>(array3u)) Plane3u;
|
||||
|
||||
p1->coeffs().setRandom();
|
||||
*p2 = *p1;
|
||||
*p3 = *p1;
|
||||
|
||||
VERIFY_IS_APPROX(p1->coeffs(), p2->coeffs());
|
||||
VERIFY_IS_APPROX(p1->coeffs(), p3->coeffs());
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DECLARE_TEST(geo_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_2( hyperplane(Hyperplane<float,3,DontAlign>()) );
|
||||
CALL_SUBTEST_2( hyperplane_alignment<float>() );
|
||||
CALL_SUBTEST_3( hyperplane(Hyperplane<double,4>()) );
|
||||
CALL_SUBTEST_4( hyperplane(Hyperplane<std::complex<double>,5>()) );
|
||||
CALL_SUBTEST_1( lines<float>() );
|
||||
CALL_SUBTEST_3( lines<double>() );
|
||||
CALL_SUBTEST_2( planes<float>() );
|
||||
CALL_SUBTEST_5( planes<double>() );
|
||||
}
|
||||
}
|
||||
133
libs/eigen/test/geo_orthomethods.cpp
Normal file
133
libs/eigen/test/geo_orthomethods.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 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/Geometry>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/SVD>
|
||||
|
||||
/* this test covers the following files:
|
||||
Geometry/OrthoMethods.h
|
||||
*/
|
||||
|
||||
template<typename Scalar> void orthomethods_3()
|
||||
{
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
|
||||
typedef Matrix<Scalar,4,1> Vector4;
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random(),
|
||||
v2 = Vector3::Random();
|
||||
|
||||
// cross product
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1));
|
||||
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();
|
||||
Vector3 vec3 = Vector3::Random();
|
||||
Matrix3 mcross;
|
||||
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));
|
||||
|
||||
// cross3
|
||||
Vector4 v40 = Vector4::Random(),
|
||||
v41 = Vector4::Random(),
|
||||
v42 = Vector4::Random();
|
||||
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;
|
||||
RealVector3 rv1 = RealVector3::Random();
|
||||
VERIFY_IS_APPROX(v1.cross(rv1.template cast<Scalar>()), v1.cross(rv1));
|
||||
VERIFY_IS_APPROX(rv1.template cast<Scalar>().cross(v1), rv1.cross(v1));
|
||||
}
|
||||
|
||||
template<typename Scalar, int Size> void orthomethods(int size=Size)
|
||||
{
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar,Size,1> VectorType;
|
||||
typedef Matrix<Scalar,3,Size> Matrix3N;
|
||||
typedef Matrix<Scalar,Size,3> MatrixN3;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
|
||||
VectorType v0 = VectorType::Random(size);
|
||||
|
||||
// unitOrthogonal
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
|
||||
VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1));
|
||||
|
||||
if (size>=3)
|
||||
{
|
||||
v0.template head<2>().setZero();
|
||||
v0.tail(size-2).setRandom();
|
||||
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
|
||||
VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1));
|
||||
}
|
||||
|
||||
// colwise/rowwise cross product
|
||||
Vector3 vec3 = Vector3::Random();
|
||||
int i = internal::random<int>(0,size-1);
|
||||
|
||||
Matrix3N mat3N(3,size), mcross3N(3,size);
|
||||
mat3N.setRandom();
|
||||
mcross3N = mat3N.colwise().cross(vec3);
|
||||
VERIFY_IS_APPROX(mcross3N.col(i), mat3N.col(i).cross(vec3));
|
||||
|
||||
MatrixN3 matN3(size,3), mcrossN3(size,3);
|
||||
matN3.setRandom();
|
||||
mcrossN3 = matN3.rowwise().cross(vec3);
|
||||
VERIFY_IS_APPROX(mcrossN3.row(i), matN3.row(i).cross(vec3));
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(geo_orthomethods)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( orthomethods_3<float>() );
|
||||
CALL_SUBTEST_2( orthomethods_3<double>() );
|
||||
CALL_SUBTEST_4( orthomethods_3<std::complex<double> >() );
|
||||
CALL_SUBTEST_1( (orthomethods<float,2>()) );
|
||||
CALL_SUBTEST_2( (orthomethods<double,2>()) );
|
||||
CALL_SUBTEST_1( (orthomethods<float,3>()) );
|
||||
CALL_SUBTEST_2( (orthomethods<double,3>()) );
|
||||
CALL_SUBTEST_3( (orthomethods<float,7>()) );
|
||||
CALL_SUBTEST_4( (orthomethods<std::complex<double>,8>()) );
|
||||
CALL_SUBTEST_5( (orthomethods<float,Dynamic>(36)) );
|
||||
CALL_SUBTEST_6( (orthomethods<double,Dynamic>(35)) );
|
||||
}
|
||||
}
|
||||
125
libs/eigen/test/geo_parametrizedline.cpp
Normal file
125
libs/eigen/test/geo_parametrizedline.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// 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 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
|
||||
*/
|
||||
using std::abs;
|
||||
const Index dim = _line.dim();
|
||||
typedef typename LineType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime, 1> VectorType;
|
||||
typedef Hyperplane<Scalar,LineType::AmbientDimAtCompileTime> HyperplaneType;
|
||||
typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime,
|
||||
HyperplaneType::AmbientDimAtCompileTime> MatrixType;
|
||||
|
||||
VectorType p0 = VectorType::Random(dim);
|
||||
VectorType p1 = VectorType::Random(dim);
|
||||
|
||||
VectorType d0 = VectorType::Random(dim).normalized();
|
||||
|
||||
LineType l0(p0, d0);
|
||||
|
||||
Scalar s0 = internal::random<Scalar>();
|
||||
Scalar s1 = abs(internal::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);
|
||||
|
||||
// intersections
|
||||
VectorType p2 = VectorType::Random(dim);
|
||||
VectorType n2 = VectorType::Random(dim).normalized();
|
||||
HyperplaneType hp(p2,n2);
|
||||
Scalar t = l0.intersectionParameter(hp);
|
||||
VectorType pi = l0.pointAt(t);
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(hp.signedDistance(pi), RealScalar(1));
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(l0.distance(pi), RealScalar(1));
|
||||
VERIFY_IS_APPROX(l0.intersectionPoint(hp), pi);
|
||||
|
||||
// transform
|
||||
if (!NumTraits<Scalar>::IsComplex)
|
||||
{
|
||||
MatrixType rot = MatrixType::Random(dim,dim).householderQr().householderQ();
|
||||
DiagonalMatrix<Scalar,LineType::AmbientDimAtCompileTime> scaling(VectorType::Random());
|
||||
Translation<Scalar,LineType::AmbientDimAtCompileTime> translation(VectorType::Random());
|
||||
|
||||
while(scaling.diagonal().cwiseAbs().minCoeff()<RealScalar(1e-4)) scaling.diagonal() = VectorType::Random();
|
||||
|
||||
LineType l1 = l0;
|
||||
VectorType p3 = l0.pointAt(Scalar(1));
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( l1.transform(rot).distance(rot * p3), Scalar(1) );
|
||||
l1 = l0;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( l1.transform(rot,Isometry).distance(rot * p3), Scalar(1) );
|
||||
l1 = l0;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( l1.transform(rot*scaling).distance((rot*scaling) * p3), Scalar(1) );
|
||||
l1 = l0;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( l1.transform(rot*scaling*translation)
|
||||
.distance((rot*scaling*translation) * p3), Scalar(1) );
|
||||
l1 = l0;
|
||||
VERIFY_IS_MUCH_SMALLER_THAN( l1.transform(rot*translation,Isometry)
|
||||
.distance((rot*translation) * p3), Scalar(1) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Scalar> void parametrizedline_alignment()
|
||||
{
|
||||
typedef ParametrizedLine<Scalar,4,AutoAlign> Line4a;
|
||||
typedef ParametrizedLine<Scalar,4,DontAlign> Line4u;
|
||||
|
||||
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;
|
||||
Line4u *p2 = ::new(reinterpret_cast<void*>(array2)) Line4u;
|
||||
Line4u *p3 = ::new(reinterpret_cast<void*>(array3u)) Line4u;
|
||||
|
||||
p1->origin().setRandom();
|
||||
p1->direction().setRandom();
|
||||
*p2 = *p1;
|
||||
*p3 = *p1;
|
||||
|
||||
VERIFY_IS_APPROX(p1->origin(), p2->origin());
|
||||
VERIFY_IS_APPROX(p1->origin(), p3->origin());
|
||||
VERIFY_IS_APPROX(p1->direction(), p2->direction());
|
||||
VERIFY_IS_APPROX(p1->direction(), p3->direction());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(geo_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_2( parametrizedline_alignment<float>() );
|
||||
CALL_SUBTEST_3( parametrizedline(ParametrizedLine<double,4>()) );
|
||||
CALL_SUBTEST_3( parametrizedline_alignment<double>() );
|
||||
CALL_SUBTEST_4( parametrizedline(ParametrizedLine<std::complex<double>,5>()) );
|
||||
}
|
||||
}
|
||||
332
libs/eigen/test/geo_quaternion.cpp
Normal file
332
libs/eigen/test/geo_quaternion.cpp
Normal file
@@ -0,0 +1,332 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2009 Mathieu Gautier <mathieu.gautier@cea.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>
|
||||
#include "AnnoyingScalar.h"
|
||||
|
||||
template<typename T> T bounded_acos(T v)
|
||||
{
|
||||
using std::acos;
|
||||
using std::min;
|
||||
using std::max;
|
||||
return acos((max)(T(-1),(min)(v,T(1))));
|
||||
}
|
||||
|
||||
template<typename QuatType> void check_slerp(const QuatType& q0, const QuatType& q1)
|
||||
{
|
||||
using std::abs;
|
||||
typedef typename QuatType::Scalar Scalar;
|
||||
typedef AngleAxis<Scalar> AA;
|
||||
|
||||
Scalar largeEps = test_precision<Scalar>();
|
||||
|
||||
Scalar theta_tot = AA(q1*q0.inverse()).angle();
|
||||
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);
|
||||
Scalar theta = AA(q*q0.inverse()).angle();
|
||||
VERIFY(abs(q.norm() - 1) < largeEps);
|
||||
if(theta_tot==0) VERIFY(theta_tot==0);
|
||||
else VERIFY(abs(theta - t * theta_tot) < largeEps);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar, int Options> void quaternion(void)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Quaternion.h
|
||||
*/
|
||||
using std::abs;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
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 = Scalar(1e-3);
|
||||
|
||||
Scalar eps = internal::random<Scalar>() * Scalar(1e-2);
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random(),
|
||||
v2 = Vector3::Random(),
|
||||
v3 = Vector3::Random();
|
||||
|
||||
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;
|
||||
q2.setIdentity();
|
||||
VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
|
||||
q1.coeffs().setRandom();
|
||||
VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
|
||||
|
||||
#ifndef EIGEN_NO_IO
|
||||
// Printing
|
||||
std::ostringstream ss;
|
||||
ss << q2;
|
||||
VERIFY(ss.str() == "0i + 0j + 0k + 1");
|
||||
#endif
|
||||
|
||||
// concatenation
|
||||
q1 *= q2;
|
||||
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
q2 = AngleAxisx(a, v1.normalized());
|
||||
|
||||
// angular distance
|
||||
Scalar refangle = abs(AngleAxisx(q1.inverse()*q2).angle());
|
||||
if (refangle>Scalar(EIGEN_PI))
|
||||
refangle = Scalar(2)*Scalar(EIGEN_PI) - refangle;
|
||||
|
||||
if((q1.coeffs()-q2.coeffs()).norm() > Scalar(10)*largeEps)
|
||||
{
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(abs(q1.angularDistance(q2) - refangle), Scalar(1));
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
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);
|
||||
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
|
||||
|
||||
// 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()) > Scalar(5)*test_precision<Scalar>()
|
||||
&& (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);
|
||||
}
|
||||
|
||||
// from two vector creation
|
||||
VERIFY_IS_APPROX( v2.normalized(),(q2.setFromTwoVectors(v1, v2)*v1).normalized());
|
||||
VERIFY_IS_APPROX( v1.normalized(),(q2.setFromTwoVectors(v1, v1)*v1).normalized());
|
||||
VERIFY_IS_APPROX(-v1.normalized(),(q2.setFromTwoVectors(v1,-v1)*v1).normalized());
|
||||
if (internal::is_same<Scalar,double>::value)
|
||||
{
|
||||
v3 = (v1.array()+eps).matrix();
|
||||
VERIFY_IS_APPROX( v3.normalized(),(q2.setFromTwoVectors(v1, v3)*v1).normalized());
|
||||
VERIFY_IS_APPROX(-v3.normalized(),(q2.setFromTwoVectors(v1,-v3)*v1).normalized());
|
||||
}
|
||||
|
||||
// from two vector creation static function
|
||||
VERIFY_IS_APPROX( v2.normalized(),(Quaternionx::FromTwoVectors(v1, v2)*v1).normalized());
|
||||
VERIFY_IS_APPROX( v1.normalized(),(Quaternionx::FromTwoVectors(v1, v1)*v1).normalized());
|
||||
VERIFY_IS_APPROX(-v1.normalized(),(Quaternionx::FromTwoVectors(v1,-v1)*v1).normalized());
|
||||
if (internal::is_same<Scalar,double>::value)
|
||||
{
|
||||
v3 = (v1.array()+eps).matrix();
|
||||
VERIFY_IS_APPROX( v3.normalized(),(Quaternionx::FromTwoVectors(v1, v3)*v1).normalized());
|
||||
VERIFY_IS_APPROX(-v3.normalized(),(Quaternionx::FromTwoVectors(v1,-v3)*v1).normalized());
|
||||
}
|
||||
|
||||
// inverse and conjugate
|
||||
VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
|
||||
VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
|
||||
|
||||
// test casting
|
||||
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);
|
||||
|
||||
// test bug 369 - improper alignment.
|
||||
Quaternionx *q = new Quaternionx;
|
||||
delete q;
|
||||
|
||||
q1 = Quaternionx::UnitRandom();
|
||||
q2 = Quaternionx::UnitRandom();
|
||||
check_slerp(q1,q2);
|
||||
|
||||
q1 = AngleAxisx(b, 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 = Quaternionx::UnitRandom();
|
||||
q2.coeffs() = -q1.coeffs();
|
||||
check_slerp(q1,q2);
|
||||
}
|
||||
|
||||
template<typename Scalar> void mapQuaternion(void){
|
||||
typedef Map<Quaternion<Scalar>, Aligned> MQuaternionA;
|
||||
typedef Map<const Quaternion<Scalar>, Aligned> MCQuaternionA;
|
||||
typedef Map<Quaternion<Scalar> > MQuaternionUA;
|
||||
typedef Map<const Quaternion<Scalar> > MCQuaternionUA;
|
||||
typedef Quaternion<Scalar> Quaternionx;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef AngleAxis<Scalar> AngleAxisx;
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random();
|
||||
Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
|
||||
|
||||
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);
|
||||
MCQuaternionA mcq1(array1);
|
||||
MQuaternionA mq2(array2);
|
||||
MQuaternionUA mq3(array3unaligned);
|
||||
MCQuaternionUA mcq3(array3unaligned);
|
||||
|
||||
// std::cerr << array1 << " " << array2 << " " << array3 << "\n";
|
||||
mq1 = AngleAxisx(a, v0.normalized());
|
||||
mq2 = mq1;
|
||||
mq3 = mq1;
|
||||
|
||||
Quaternionx q1 = mq1;
|
||||
Quaternionx q2 = mq2;
|
||||
Quaternionx q3 = mq3;
|
||||
Quaternionx q4 = MCQuaternionUA(array3unaligned);
|
||||
|
||||
VERIFY_IS_APPROX(q1.coeffs(), q2.coeffs());
|
||||
VERIFY_IS_APPROX(q1.coeffs(), q3.coeffs());
|
||||
VERIFY_IS_APPROX(q4.coeffs(), q3.coeffs());
|
||||
|
||||
VERIFY_IS_APPROX(mq1 * (mq1.inverse() * v1), v1);
|
||||
VERIFY_IS_APPROX(mq1 * (mq1.conjugate() * v1), v1);
|
||||
|
||||
VERIFY_IS_APPROX(mcq1 * (mcq1.inverse() * v1), v1);
|
||||
VERIFY_IS_APPROX(mcq1 * (mcq1.conjugate() * v1), v1);
|
||||
|
||||
VERIFY_IS_APPROX(mq3 * (mq3.inverse() * v1), v1);
|
||||
VERIFY_IS_APPROX(mq3 * (mq3.conjugate() * v1), v1);
|
||||
|
||||
VERIFY_IS_APPROX(mcq3 * (mcq3.inverse() * v1), v1);
|
||||
VERIFY_IS_APPROX(mcq3 * (mcq3.conjugate() * v1), v1);
|
||||
|
||||
VERIFY_IS_APPROX(mq1*mq2, q1*q2);
|
||||
VERIFY_IS_APPROX(mq3*mq2, q3*q2);
|
||||
VERIFY_IS_APPROX(mcq1*mq2, q1*q2);
|
||||
VERIFY_IS_APPROX(mcq3*mq2, q3*q2);
|
||||
|
||||
// Bug 1461, compilation issue with Map<const Quat>::w(), and other reference/constness checks:
|
||||
VERIFY_IS_APPROX(mcq3.coeffs().x() + mcq3.coeffs().y() + mcq3.coeffs().z() + mcq3.coeffs().w(), mcq3.coeffs().sum());
|
||||
VERIFY_IS_APPROX(mcq3.x() + mcq3.y() + mcq3.z() + mcq3.w(), mcq3.coeffs().sum());
|
||||
mq3.w() = 1;
|
||||
const Quaternionx& cq3(q3);
|
||||
VERIFY( &cq3.x() == &q3.x() );
|
||||
const MQuaternionUA& cmq3(mq3);
|
||||
VERIFY( &cmq3.x() == &mq3.x() );
|
||||
// FIXME the following should be ok. The problem is that currently the LValueBit flag
|
||||
// is used to determine whether we can return a coeff by reference or not, which is not enough for Map<const ...>.
|
||||
//const MCQuaternionUA& cmcq3(mcq3);
|
||||
//VERIFY( &cmcq3.x() == &mcq3.x() );
|
||||
|
||||
// test cast
|
||||
{
|
||||
Quaternion<float> q1f = mq1.template cast<float>();
|
||||
VERIFY_IS_APPROX(q1f.template cast<Scalar>(),mq1);
|
||||
Quaternion<double> q1d = mq1.template cast<double>();
|
||||
VERIFY_IS_APPROX(q1d.template cast<Scalar>(),mq1);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar> void quaternionAlignment(void){
|
||||
typedef Quaternion<Scalar,AutoAlign> QuaternionA;
|
||||
typedef Quaternion<Scalar,DontAlign> QuaternionUA;
|
||||
|
||||
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;
|
||||
QuaternionUA *q2 = ::new(reinterpret_cast<void*>(array2)) QuaternionUA;
|
||||
QuaternionUA *q3 = ::new(reinterpret_cast<void*>(arrayunaligned)) QuaternionUA;
|
||||
|
||||
q1->coeffs().setRandom();
|
||||
*q2 = *q1;
|
||||
*q3 = *q1;
|
||||
|
||||
VERIFY_IS_APPROX(q1->coeffs(), q2->coeffs());
|
||||
VERIFY_IS_APPROX(q1->coeffs(), q3->coeffs());
|
||||
}
|
||||
|
||||
template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
|
||||
{
|
||||
// there's a lot that we can't test here while still having this test compile!
|
||||
// the only possible approach would be to run a script trying to compile stuff and checking that it fails.
|
||||
// CMake can help with that.
|
||||
|
||||
// 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( !(Map<ConstPlainObjectType>::Flags & LvalueBit) );
|
||||
VERIFY( !(Map<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_RVALUE_REFERENCES
|
||||
|
||||
// Regression for bug 1573
|
||||
struct MovableClass {
|
||||
// The following line is a workaround for gcc 4.7 and 4.8 (see bug 1573 comments).
|
||||
static_assert(std::is_nothrow_move_constructible<Quaternionf>::value,"");
|
||||
MovableClass() = default;
|
||||
MovableClass(const MovableClass&) = default;
|
||||
MovableClass(MovableClass&&) noexcept = default;
|
||||
MovableClass& operator=(const MovableClass&) = default;
|
||||
MovableClass& operator=(MovableClass&&) = default;
|
||||
Quaternionf m_quat;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
EIGEN_DECLARE_TEST(geo_quaternion)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1(( quaternion<float,AutoAlign>() ));
|
||||
CALL_SUBTEST_1( check_const_correctness(Quaternionf()) );
|
||||
CALL_SUBTEST_1(( quaternion<float,DontAlign>() ));
|
||||
CALL_SUBTEST_1(( quaternionAlignment<float>() ));
|
||||
CALL_SUBTEST_1( mapQuaternion<float>() );
|
||||
|
||||
CALL_SUBTEST_2(( quaternion<double,AutoAlign>() ));
|
||||
CALL_SUBTEST_2( check_const_correctness(Quaterniond()) );
|
||||
CALL_SUBTEST_2(( quaternion<double,DontAlign>() ));
|
||||
CALL_SUBTEST_2(( quaternionAlignment<double>() ));
|
||||
CALL_SUBTEST_2( mapQuaternion<double>() );
|
||||
|
||||
#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
|
||||
AnnoyingScalar::dont_throw = true;
|
||||
#endif
|
||||
CALL_SUBTEST_3(( quaternion<AnnoyingScalar,AutoAlign>() ));
|
||||
}
|
||||
}
|
||||
731
libs/eigen/test/geo_transformations.cpp
Normal file
731
libs/eigen/test/geo_transformations.cpp
Normal file
@@ -0,0 +1,731 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 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/Geometry>
|
||||
#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:
|
||||
Cross.h Quaternion.h, Transform.cpp
|
||||
*/
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef Quaternion<Scalar> Quaternionx;
|
||||
typedef AngleAxis<Scalar> AngleAxisx;
|
||||
typedef Transform<Scalar,3,Mode,Options> Transform3;
|
||||
typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
|
||||
typedef Translation<Scalar,3> Translation3;
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random();
|
||||
|
||||
Transform3 t0, t1, t2;
|
||||
|
||||
Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
|
||||
|
||||
Quaternionx q1, q2;
|
||||
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
|
||||
t0 = Transform3::Identity();
|
||||
VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
|
||||
|
||||
t0.linear() = q1.toRotationMatrix();
|
||||
|
||||
v0 << 50, 2, 1;
|
||||
t0.scale(v0);
|
||||
|
||||
VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).template head<3>().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.cwiseInverse());
|
||||
t1.translate(-v0);
|
||||
|
||||
VERIFY((t0 * 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);
|
||||
|
||||
// translation * vector
|
||||
t0.setIdentity();
|
||||
t0.translate(v0);
|
||||
VERIFY_IS_APPROX((t0 * v1).template head<3>(), Translation3(v0) * v1);
|
||||
|
||||
// AlignedScaling * vector
|
||||
t0.setIdentity();
|
||||
t0.scale(v0);
|
||||
VERIFY_IS_APPROX((t0 * v1).template head<3>(), AlignedScaling3(v0) * v1);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Mode, int Options> void transformations()
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Cross.h Quaternion.h, Transform.cpp
|
||||
*/
|
||||
using std::cos;
|
||||
using std::abs;
|
||||
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,Mode,Options> Transform2;
|
||||
typedef Transform<Scalar,3,Mode,Options> Transform3;
|
||||
typedef typename Transform3::MatrixType MatrixType;
|
||||
typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
|
||||
typedef Translation<Scalar,2> Translation2;
|
||||
typedef Translation<Scalar,3> Translation3;
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random();
|
||||
Matrix3 matrot1, m;
|
||||
|
||||
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(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));
|
||||
}
|
||||
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);
|
||||
|
||||
Quaternionx q1, q2;
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
q2 = AngleAxisx(a, v1.normalized());
|
||||
|
||||
// rotation matrix conversion
|
||||
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 = AngleAxisx(q1);
|
||||
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
|
||||
|
||||
// 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);
|
||||
// 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) );
|
||||
}
|
||||
|
||||
// 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 (abs(a)<Scalar(0.1))
|
||||
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;
|
||||
|
||||
// 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.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.cwiseInverse());
|
||||
t1.translate(-v0);
|
||||
|
||||
VERIFY((t0 * t1).matrix().isIdentity(test_precision<Scalar>()));
|
||||
|
||||
t1.fromPositionOrientationScale(v0, q1, v1);
|
||||
VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
|
||||
|
||||
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);
|
||||
if(Mode!=int(AffineCompact))
|
||||
tmat4.matrix()(3,3) = Scalar(1);
|
||||
VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
|
||||
|
||||
Scalar a3 = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_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(), MatrixType::Identity());
|
||||
t4 *= aa3;
|
||||
VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
|
||||
|
||||
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).eval());
|
||||
VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
|
||||
t4 *= tv3;
|
||||
VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
|
||||
|
||||
AlignedScaling3 sv3(v3);
|
||||
Transform3 t6(sv3);
|
||||
t4 = sv3;
|
||||
VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
|
||||
t4.scale(v3.cwiseInverse());
|
||||
VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
|
||||
t4 *= sv3;
|
||||
VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
|
||||
|
||||
// matrix * transform
|
||||
VERIFY_IS_APPROX((t3.matrix()*t4).matrix(), (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 (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.cwiseInverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
|
||||
|
||||
// Transform - new API
|
||||
// 3D
|
||||
t0.setIdentity();
|
||||
t0.rotate(q1).scale(v0).translate(v0);
|
||||
// mat * aligned scaling and mat * translation
|
||||
t1 = (Matrix3(q1) * AlignedScaling3(v0)) * Translation3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
t1 = (Matrix3(q1) * Eigen::Scaling(v0)) * Translation3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
t1 = (q1 * Eigen::Scaling(v0)) * Translation3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// mat * transformation and aligned scaling * translation
|
||||
t1 = Matrix3(q1) * (AlignedScaling3(v0) * Translation3(v0));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
|
||||
t0.setIdentity();
|
||||
t0.scale(s0).translate(v0);
|
||||
t1 = Eigen::Scaling(s0) * Translation3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
t0.prescale(s0);
|
||||
t1 = Eigen::Scaling(s0) * t1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0 = t3;
|
||||
t0.scale(s0);
|
||||
t1 = t3 * Eigen::Scaling(s0,s0,s0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
t0.prescale(s0);
|
||||
t1 = Eigen::Scaling(s0,s0,s0) * t1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0 = t3;
|
||||
t0.scale(s0);
|
||||
t1 = t3 * Eigen::Scaling(s0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
t0.prescale(s0);
|
||||
t1 = Eigen::Scaling(s0) * t1;
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0.setIdentity();
|
||||
t0.prerotate(q1).prescale(v0).pretranslate(v0);
|
||||
// translation * aligned scaling and transformation * mat
|
||||
t1 = (Translation3(v0) * AlignedScaling3(v0)) * Transform3(q1);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// scaling * mat and translation * mat
|
||||
t1 = Translation3(v0) * (AlignedScaling3(v0) * Transform3(q1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
t0.setIdentity();
|
||||
t0.scale(v0).translate(v0).rotate(q1);
|
||||
// translation * mat and aligned scaling * transformation
|
||||
t1 = AlignedScaling3(v0) * (Translation3(v0) * Transform3(q1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
// transformation * aligned scaling
|
||||
t0.scale(v0);
|
||||
t1 *= AlignedScaling3(v0);
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
t1 = AlignedScaling3(v0) * (Translation3(v0) * Transform3(q1));
|
||||
t1 = t1 * v0.asDiagonal();
|
||||
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());
|
||||
|
||||
// aligned scaling * quaternion
|
||||
t0.scale(v1).rotate(q1);
|
||||
t1 = t1 * (AlignedScaling3(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 * aligned scaling
|
||||
t0.rotate(q1).scale(v1);
|
||||
t1 = t1 * (q1 * AlignedScaling3(v1));
|
||||
VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
|
||||
|
||||
// test transform inversion
|
||||
t0.setIdentity();
|
||||
t0.translate(v0);
|
||||
do {
|
||||
t0.linear().setRandom();
|
||||
} while(t0.linear().jacobiSvd().singularValues()(2)<test_precision<Scalar>());
|
||||
Matrix4 t044 = Matrix4::Zero();
|
||||
t044(3,3) = 1;
|
||||
t044.block(0,0,t0.matrix().rows(),4) = t0.matrix();
|
||||
VERIFY_IS_APPROX(t0.inverse(Affine).matrix(), t044.inverse().block(0,0,t0.matrix().rows(),4));
|
||||
t0.setIdentity();
|
||||
t0.translate(v0).rotate(q1);
|
||||
t044 = Matrix4::Zero();
|
||||
t044(3,3) = 1;
|
||||
t044.block(0,0,t0.matrix().rows(),4) = t0.matrix();
|
||||
VERIFY_IS_APPROX(t0.inverse(Isometry).matrix(), t044.inverse().block(0,0,t0.matrix().rows(),4));
|
||||
|
||||
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,Mode> t1f = t1.template cast<float>();
|
||||
VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
|
||||
Transform<double,3,Mode> 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);
|
||||
|
||||
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(internal::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);
|
||||
|
||||
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);
|
||||
|
||||
t20 = Translation2(v20) * (R0 * R0.inverse() * Eigen::Scaling(s0));
|
||||
t21 = Translation2(v20) * Eigen::Scaling(s0);
|
||||
VERIFY_IS_APPROX(t20,t21);
|
||||
|
||||
VERIFY_IS_APPROX(s0, (R0.slerp(0, R1)).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
|
||||
{
|
||||
Rotation2D<Scalar> r1; // default ctor
|
||||
r1 = Rotation2D<Scalar>(s0); // copy assignment
|
||||
VERIFY_IS_APPROX(r1.angle(),s0);
|
||||
Rotation2D<Scalar> r2(r1); // copy ctor
|
||||
VERIFY_IS_APPROX(r2.angle(),s0);
|
||||
}
|
||||
|
||||
{
|
||||
Transform3 t32(Matrix4::Random()), t33, t34;
|
||||
t34 = t33 = t32;
|
||||
t32.scale(v0);
|
||||
t33*=AlignedScaling3(v0);
|
||||
VERIFY_IS_APPROX(t32.matrix(), t33.matrix());
|
||||
t33 = t34 * AlignedScaling3(v0);
|
||||
VERIFY_IS_APPROX(t32.matrix(), t33.matrix());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename A1, typename A2, typename P, typename Q, typename V, typename H>
|
||||
void transform_associativity_left(const A1& a1, const A2& a2, const P& p, const Q& q, const V& v, const H& h)
|
||||
{
|
||||
VERIFY_IS_APPROX( q*(a1*v), (q*a1)*v );
|
||||
VERIFY_IS_APPROX( q*(a2*v), (q*a2)*v );
|
||||
VERIFY_IS_APPROX( q*(p*h).hnormalized(), ((q*p)*h).hnormalized() );
|
||||
}
|
||||
|
||||
template<typename A1, typename A2, typename P, typename Q, typename V, typename H>
|
||||
void transform_associativity2(const A1& a1, const A2& a2, const P& p, const Q& q, const V& v, const H& h)
|
||||
{
|
||||
VERIFY_IS_APPROX( a1*(q*v), (a1*q)*v );
|
||||
VERIFY_IS_APPROX( a2*(q*v), (a2*q)*v );
|
||||
VERIFY_IS_APPROX( p *(q*v).homogeneous(), (p *q)*v.homogeneous() );
|
||||
|
||||
transform_associativity_left(a1, a2,p, q, v, h);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, int Options,typename RotationType>
|
||||
void transform_associativity(const RotationType& R)
|
||||
{
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
typedef Matrix<Scalar,Dim+1,1> HVectorType;
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearType;
|
||||
typedef Matrix<Scalar,Dim+1,Dim+1> MatrixType;
|
||||
typedef Transform<Scalar,Dim,AffineCompact,Options> AffineCompactType;
|
||||
typedef Transform<Scalar,Dim,Affine,Options> AffineType;
|
||||
typedef Transform<Scalar,Dim,Projective,Options> ProjectiveType;
|
||||
typedef DiagonalMatrix<Scalar,Dim> ScalingType;
|
||||
typedef Translation<Scalar,Dim> TranslationType;
|
||||
|
||||
AffineCompactType A1c; A1c.matrix().setRandom();
|
||||
AffineCompactType A2c; A2c.matrix().setRandom();
|
||||
AffineType A1(A1c);
|
||||
AffineType A2(A2c);
|
||||
ProjectiveType P1; P1.matrix().setRandom();
|
||||
VectorType v1 = VectorType::Random();
|
||||
VectorType v2 = VectorType::Random();
|
||||
HVectorType h1 = HVectorType::Random();
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
LinearType L = LinearType::Random();
|
||||
MatrixType M = MatrixType::Random();
|
||||
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, A2, v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, A2c, v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, v1.asDiagonal(), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, ScalingType(v1), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, Scaling(v1), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, Scaling(s1), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, TranslationType(v1), v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity_left(A1c, A1, P1, L, v2, h1) );
|
||||
CALL_SUBTEST( transform_associativity2(A1c, A1, P1, R, v2, h1) );
|
||||
|
||||
VERIFY_IS_APPROX( A1*(M*h1), (A1*M)*h1 );
|
||||
VERIFY_IS_APPROX( A1c*(M*h1), (A1c*M)*h1 );
|
||||
VERIFY_IS_APPROX( P1*(M*h1), (P1*M)*h1 );
|
||||
|
||||
VERIFY_IS_APPROX( M*(A1*h1), (M*A1)*h1 );
|
||||
VERIFY_IS_APPROX( M*(A1c*h1), (M*A1c)*h1 );
|
||||
VERIFY_IS_APPROX( M*(P1*h1), ((M*P1)*h1) );
|
||||
}
|
||||
|
||||
template<typename Scalar> void transform_alignment()
|
||||
{
|
||||
typedef Transform<Scalar,3,Projective,AutoAlign> Projective3a;
|
||||
typedef Transform<Scalar,3,Projective,DontAlign> Projective3u;
|
||||
|
||||
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;
|
||||
Projective3u *p2 = ::new(reinterpret_cast<void*>(array2)) Projective3u;
|
||||
Projective3u *p3 = ::new(reinterpret_cast<void*>(array3u)) Projective3u;
|
||||
|
||||
p1->matrix().setRandom();
|
||||
*p2 = *p1;
|
||||
*p3 = *p1;
|
||||
|
||||
VERIFY_IS_APPROX(p1->matrix(), p2->matrix());
|
||||
VERIFY_IS_APPROX(p1->matrix(), p3->matrix());
|
||||
|
||||
VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3));
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, int Options> void transform_products()
|
||||
{
|
||||
typedef Matrix<Scalar,Dim+1,Dim+1> Mat;
|
||||
typedef Transform<Scalar,Dim,Projective,Options> Proj;
|
||||
typedef Transform<Scalar,Dim,Affine,Options> Aff;
|
||||
typedef Transform<Scalar,Dim,AffineCompact,Options> AffC;
|
||||
|
||||
Proj p; p.matrix().setRandom();
|
||||
Aff a; a.linear().setRandom(); a.translation().setRandom();
|
||||
AffC ac = a;
|
||||
|
||||
Mat p_m(p.matrix()), a_m(a.matrix());
|
||||
|
||||
VERIFY_IS_APPROX((p*p).matrix(), p_m*p_m);
|
||||
VERIFY_IS_APPROX((a*a).matrix(), a_m*a_m);
|
||||
VERIFY_IS_APPROX((p*a).matrix(), p_m*a_m);
|
||||
VERIFY_IS_APPROX((a*p).matrix(), a_m*p_m);
|
||||
VERIFY_IS_APPROX((ac*a).matrix(), a_m*a_m);
|
||||
VERIFY_IS_APPROX((a*ac).matrix(), a_m*a_m);
|
||||
VERIFY_IS_APPROX((p*ac).matrix(), p_m*a_m);
|
||||
VERIFY_IS_APPROX((ac*p).matrix(), a_m*p_m);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Mode, int Options> void transformations_no_scale()
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Cross.h Quaternion.h, Transform.h
|
||||
*/
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef Matrix<Scalar,4,1> Vector4;
|
||||
typedef Quaternion<Scalar> Quaternionx;
|
||||
typedef AngleAxis<Scalar> AngleAxisx;
|
||||
typedef Transform<Scalar,3,Mode,Options> Transform3;
|
||||
typedef Translation<Scalar,3> Translation3;
|
||||
typedef Matrix<Scalar,4,4> Matrix4;
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random();
|
||||
|
||||
Transform3 t0, t1, t2;
|
||||
|
||||
Scalar a = internal::random<Scalar>(-Scalar(EIGEN_PI), Scalar(EIGEN_PI));
|
||||
|
||||
Quaternionx q1, q2;
|
||||
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
|
||||
t0 = Transform3::Identity();
|
||||
VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
|
||||
|
||||
t0.setIdentity();
|
||||
t1.setIdentity();
|
||||
v1 = Vector3::Ones();
|
||||
t0.linear() = q1.toRotationMatrix();
|
||||
t0.pretranslate(v0);
|
||||
t1.linear() = q1.conjugate().toRotationMatrix();
|
||||
t1.translate(-v0);
|
||||
|
||||
VERIFY((t0 * 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);
|
||||
|
||||
// translation * vector
|
||||
t0.setIdentity();
|
||||
t0.translate(v0);
|
||||
VERIFY_IS_APPROX((t0 * v1).template head<3>(), Translation3(v0) * v1);
|
||||
|
||||
// Conversion to matrix.
|
||||
Transform3 t3;
|
||||
t3.linear() = q1.toRotationMatrix();
|
||||
t3.translation() = v1;
|
||||
Matrix4 m3 = t3.matrix();
|
||||
VERIFY((m3 * m3.inverse()).isIdentity(test_precision<Scalar>()));
|
||||
// Verify implicit last row is initialized.
|
||||
VERIFY_IS_APPROX(Vector4(m3.row(3)), Vector4(0.0, 0.0, 0.0, 1.0));
|
||||
|
||||
VERIFY_IS_APPROX(t3.rotation(), t3.linear());
|
||||
if(Mode==Isometry)
|
||||
VERIFY(t3.rotation().data()==t3.linear().data());
|
||||
}
|
||||
|
||||
template<typename Scalar, int Mode, int Options> void transformations_computed_scaling_continuity()
|
||||
{
|
||||
typedef Matrix<Scalar, 3, 1> Vector3;
|
||||
typedef Transform<Scalar, 3, Mode, Options> Transform3;
|
||||
typedef Matrix<Scalar, 3, 3> Matrix3;
|
||||
|
||||
// Given: two transforms that differ by '2*eps'.
|
||||
Scalar eps(1e-3);
|
||||
Vector3 v0 = Vector3::Random().normalized(),
|
||||
v1 = Vector3::Random().normalized(),
|
||||
v3 = Vector3::Random().normalized();
|
||||
Transform3 t0, t1;
|
||||
// The interesting case is when their determinants have different signs.
|
||||
Matrix3 rank2 = 50 * v0 * v0.adjoint() + 20 * v1 * v1.adjoint();
|
||||
t0.linear() = rank2 + eps * v3 * v3.adjoint();
|
||||
t1.linear() = rank2 - eps * v3 * v3.adjoint();
|
||||
|
||||
// When: computing the rotation-scaling parts
|
||||
Matrix3 r0, s0, r1, s1;
|
||||
t0.computeRotationScaling(&r0, &s0);
|
||||
t1.computeRotationScaling(&r1, &s1);
|
||||
|
||||
// Then: the scaling parts should differ by no more than '2*eps'.
|
||||
const Scalar c(2.1); // 2 + room for rounding errors
|
||||
VERIFY((s0 - s1).norm() < c * eps);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(geo_transformations)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1(( transformations<double,Affine,AutoAlign>() ));
|
||||
CALL_SUBTEST_1(( non_projective_only<double,Affine,AutoAlign>() ));
|
||||
CALL_SUBTEST_1(( transformations_computed_scaling_continuity<double,Affine,AutoAlign>() ));
|
||||
|
||||
CALL_SUBTEST_2(( transformations<float,AffineCompact,AutoAlign>() ));
|
||||
CALL_SUBTEST_2(( non_projective_only<float,AffineCompact,AutoAlign>() ));
|
||||
CALL_SUBTEST_2(( transform_alignment<float>() ));
|
||||
|
||||
CALL_SUBTEST_3(( transformations<double,Projective,AutoAlign>() ));
|
||||
CALL_SUBTEST_3(( transformations<double,Projective,DontAlign>() ));
|
||||
CALL_SUBTEST_3(( transform_alignment<double>() ));
|
||||
|
||||
CALL_SUBTEST_4(( transformations<float,Affine,RowMajor|AutoAlign>() ));
|
||||
CALL_SUBTEST_4(( non_projective_only<float,Affine,RowMajor>() ));
|
||||
|
||||
CALL_SUBTEST_5(( transformations<double,AffineCompact,RowMajor|AutoAlign>() ));
|
||||
CALL_SUBTEST_5(( non_projective_only<double,AffineCompact,RowMajor>() ));
|
||||
|
||||
CALL_SUBTEST_6(( transformations<double,Projective,RowMajor|AutoAlign>() ));
|
||||
CALL_SUBTEST_6(( transformations<double,Projective,RowMajor|DontAlign>() ));
|
||||
|
||||
|
||||
CALL_SUBTEST_7(( transform_products<double,3,RowMajor|AutoAlign>() ));
|
||||
CALL_SUBTEST_7(( transform_products<float,2,AutoAlign>() ));
|
||||
|
||||
CALL_SUBTEST_8(( transform_associativity<double,2,ColMajor>(Rotation2D<double>(internal::random<double>()*double(EIGEN_PI))) ));
|
||||
CALL_SUBTEST_8(( transform_associativity<double,3,ColMajor>(Quaterniond::UnitRandom()) ));
|
||||
|
||||
CALL_SUBTEST_9(( transformations_no_scale<double,Affine,AutoAlign>() ));
|
||||
CALL_SUBTEST_9(( transformations_no_scale<double,Isometry,AutoAlign>() ));
|
||||
}
|
||||
}
|
||||
461
libs/eigen/test/gpu_basic.cu
Normal file
461
libs/eigen/test/gpu_basic.cu
Normal file
@@ -0,0 +1,461 @@
|
||||
// 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_DEFAULT_DENSE_INDEX_TYPE int
|
||||
|
||||
#include "main.h"
|
||||
#include "gpu_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 complex_sqrt {
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
|
||||
{
|
||||
using namespace Eigen;
|
||||
typedef typename T::Scalar ComplexType;
|
||||
typedef typename T::Scalar::value_type ValueType;
|
||||
const int num_special_inputs = 18;
|
||||
|
||||
if (i == 0) {
|
||||
const ValueType nan = std::numeric_limits<ValueType>::quiet_NaN();
|
||||
typedef Eigen::Vector<ComplexType, num_special_inputs> SpecialInputs;
|
||||
SpecialInputs special_in;
|
||||
special_in.setZero();
|
||||
int idx = 0;
|
||||
special_in[idx++] = ComplexType(0, 0);
|
||||
special_in[idx++] = ComplexType(-0, 0);
|
||||
special_in[idx++] = ComplexType(0, -0);
|
||||
special_in[idx++] = ComplexType(-0, -0);
|
||||
// GCC's fallback sqrt implementation fails for inf inputs.
|
||||
// It is called when _GLIBCXX_USE_C99_COMPLEX is false or if
|
||||
// clang includes the GCC header (which temporarily disables
|
||||
// _GLIBCXX_USE_C99_COMPLEX)
|
||||
#if !defined(_GLIBCXX_COMPLEX) || \
|
||||
(_GLIBCXX_USE_C99_COMPLEX && !defined(__CLANG_CUDA_WRAPPERS_COMPLEX))
|
||||
const ValueType inf = std::numeric_limits<ValueType>::infinity();
|
||||
special_in[idx++] = ComplexType(1.0, inf);
|
||||
special_in[idx++] = ComplexType(nan, inf);
|
||||
special_in[idx++] = ComplexType(1.0, -inf);
|
||||
special_in[idx++] = ComplexType(nan, -inf);
|
||||
special_in[idx++] = ComplexType(-inf, 1.0);
|
||||
special_in[idx++] = ComplexType(inf, 1.0);
|
||||
special_in[idx++] = ComplexType(-inf, -1.0);
|
||||
special_in[idx++] = ComplexType(inf, -1.0);
|
||||
special_in[idx++] = ComplexType(-inf, nan);
|
||||
special_in[idx++] = ComplexType(inf, nan);
|
||||
#endif
|
||||
special_in[idx++] = ComplexType(1.0, nan);
|
||||
special_in[idx++] = ComplexType(nan, 1.0);
|
||||
special_in[idx++] = ComplexType(nan, -1.0);
|
||||
special_in[idx++] = ComplexType(nan, nan);
|
||||
|
||||
Map<SpecialInputs> special_out(out);
|
||||
special_out = special_in.cwiseSqrt();
|
||||
}
|
||||
|
||||
T x1(in + i);
|
||||
Map<T> res(out + num_special_inputs + i*T::MaxSizeAtCompileTime);
|
||||
res = x1.cwiseSqrt();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct complex_operators {
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
|
||||
{
|
||||
using namespace Eigen;
|
||||
typedef typename T::Scalar ComplexType;
|
||||
typedef typename T::Scalar::value_type ValueType;
|
||||
const int num_scalar_operators = 24;
|
||||
const int num_vector_operators = 23; // no unary + operator.
|
||||
int out_idx = i * (num_scalar_operators + num_vector_operators * T::MaxSizeAtCompileTime);
|
||||
|
||||
// Scalar operators.
|
||||
const ComplexType a = in[i];
|
||||
const ComplexType b = in[i + 1];
|
||||
|
||||
out[out_idx++] = +a;
|
||||
out[out_idx++] = -a;
|
||||
|
||||
out[out_idx++] = a + b;
|
||||
out[out_idx++] = a + numext::real(b);
|
||||
out[out_idx++] = numext::real(a) + b;
|
||||
out[out_idx++] = a - b;
|
||||
out[out_idx++] = a - numext::real(b);
|
||||
out[out_idx++] = numext::real(a) - b;
|
||||
out[out_idx++] = a * b;
|
||||
out[out_idx++] = a * numext::real(b);
|
||||
out[out_idx++] = numext::real(a) * b;
|
||||
out[out_idx++] = a / b;
|
||||
out[out_idx++] = a / numext::real(b);
|
||||
out[out_idx++] = numext::real(a) / b;
|
||||
|
||||
out[out_idx] = a; out[out_idx++] += b;
|
||||
out[out_idx] = a; out[out_idx++] -= b;
|
||||
out[out_idx] = a; out[out_idx++] *= b;
|
||||
out[out_idx] = a; out[out_idx++] /= b;
|
||||
|
||||
const ComplexType true_value = ComplexType(ValueType(1), ValueType(0));
|
||||
const ComplexType false_value = ComplexType(ValueType(0), ValueType(0));
|
||||
out[out_idx++] = (a == b ? true_value : false_value);
|
||||
out[out_idx++] = (a == numext::real(b) ? true_value : false_value);
|
||||
out[out_idx++] = (numext::real(a) == b ? true_value : false_value);
|
||||
out[out_idx++] = (a != b ? true_value : false_value);
|
||||
out[out_idx++] = (a != numext::real(b) ? true_value : false_value);
|
||||
out[out_idx++] = (numext::real(a) != b ? true_value : false_value);
|
||||
|
||||
// Vector versions.
|
||||
T x1(in + i);
|
||||
T x2(in + i + 1);
|
||||
const int res_size = T::MaxSizeAtCompileTime * num_scalar_operators;
|
||||
const int size = T::MaxSizeAtCompileTime;
|
||||
int block_idx = 0;
|
||||
|
||||
Map<VectorX<ComplexType>> res(out + out_idx, res_size);
|
||||
res.segment(block_idx, size) = -x1;
|
||||
block_idx += size;
|
||||
|
||||
res.segment(block_idx, size) = x1 + x2;
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1 + x2.real();
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1.real() + x2;
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1 - x2;
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1 - x2.real();
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1.real() - x2;
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1.array() * x2.array();
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1.array() * x2.real().array();
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1.real().array() * x2.array();
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1.array() / x2.array();
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1.array() / x2.real().array();
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1.real().array() / x2.array();
|
||||
block_idx += size;
|
||||
|
||||
res.segment(block_idx, size) = x1; res.segment(block_idx, size) += x2;
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1; res.segment(block_idx, size) -= x2;
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1; res.segment(block_idx, size).array() *= x2.array();
|
||||
block_idx += size;
|
||||
res.segment(block_idx, size) = x1; res.segment(block_idx, size).array() /= x2.array();
|
||||
block_idx += size;
|
||||
|
||||
const T true_vector = T::Constant(true_value);
|
||||
const T false_vector = T::Constant(false_value);
|
||||
res.segment(block_idx, size) = (x1 == x2 ? true_vector : false_vector);
|
||||
block_idx += size;
|
||||
// Mixing types in equality comparison does not work.
|
||||
// res.segment(block_idx, size) = (x1 == x2.real() ? true_vector : false_vector);
|
||||
// block_idx += size;
|
||||
// res.segment(block_idx, size) = (x1.real() == x2 ? true_vector : false_vector);
|
||||
// block_idx += size;
|
||||
res.segment(block_idx, size) = (x1 != x2 ? true_vector : false_vector);
|
||||
block_idx += size;
|
||||
// res.segment(block_idx, size) = (x1 != x2.real() ? true_vector : false_vector);
|
||||
// block_idx += size;
|
||||
// res.segment(block_idx, size) = (x1.real() != x2 ? true_vector : false_vector);
|
||||
// block_idx += size;
|
||||
}
|
||||
};
|
||||
|
||||
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 alloc_new_delete {
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
|
||||
{
|
||||
int offset = 2*i*T::MaxSizeAtCompileTime;
|
||||
T* x = new T(in + offset);
|
||||
Eigen::Map<T> u(out + offset);
|
||||
u = *x;
|
||||
delete x;
|
||||
|
||||
offset += T::MaxSizeAtCompileTime;
|
||||
T* y = new T[1];
|
||||
y[0] = T(in + offset);
|
||||
Eigen::Map<T> v(out + offset);
|
||||
v = y[0];
|
||||
delete[] y;
|
||||
}
|
||||
};
|
||||
|
||||
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_direct {
|
||||
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(A);
|
||||
res = eig.eigenvalues();
|
||||
}
|
||||
};
|
||||
|
||||
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.compute(A);
|
||||
res = eig.eigenvalues();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct matrix_inverse {
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
|
||||
{
|
||||
using namespace Eigen;
|
||||
T M(in+i);
|
||||
Map<T> res(out+i*T::MaxSizeAtCompileTime);
|
||||
res = M.inverse();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct numeric_limits_test {
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator()(int i, const typename T::Scalar* in, typename T::Scalar* out) const
|
||||
{
|
||||
EIGEN_UNUSED_VARIABLE(in)
|
||||
int out_idx = i * 5;
|
||||
out[out_idx++] = numext::numeric_limits<float>::epsilon();
|
||||
out[out_idx++] = (numext::numeric_limits<float>::max)();
|
||||
out[out_idx++] = (numext::numeric_limits<float>::min)();
|
||||
out[out_idx++] = numext::numeric_limits<float>::infinity();
|
||||
out[out_idx++] = numext::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Type1, typename Type2>
|
||||
bool verifyIsApproxWithInfsNans(const Type1& a, const Type2& b, typename Type1::Scalar* = 0) // Enabled for Eigen's type only
|
||||
{
|
||||
if (a.rows() != b.rows()) {
|
||||
return false;
|
||||
}
|
||||
if (a.cols() != b.cols()) {
|
||||
return false;
|
||||
}
|
||||
for (Index r = 0; r < a.rows(); ++r) {
|
||||
for (Index c = 0; c < a.cols(); ++c) {
|
||||
if (a(r, c) != b(r, c)
|
||||
&& !((numext::isnan)(a(r, c)) && (numext::isnan)(b(r, c)))
|
||||
&& !test_isApprox(a(r, c), b(r, c))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Kernel, typename Input, typename Output>
|
||||
void test_with_infs_nans(const Kernel& ker, int n, const Input& in, Output& out)
|
||||
{
|
||||
Output out_ref, out_gpu;
|
||||
#if !defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
out_ref = out_gpu = out;
|
||||
#else
|
||||
EIGEN_UNUSED_VARIABLE(in);
|
||||
EIGEN_UNUSED_VARIABLE(out);
|
||||
#endif
|
||||
run_on_cpu (ker, n, in, out_ref);
|
||||
run_on_gpu(ker, n, in, out_gpu);
|
||||
#if !defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
verifyIsApproxWithInfsNans(out_ref, out_gpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(gpu_basic)
|
||||
{
|
||||
ei_test_init_gpu();
|
||||
|
||||
int nthreads = 100;
|
||||
Eigen::VectorXf in, out;
|
||||
Eigen::VectorXcf cfin, cfout;
|
||||
|
||||
#if !defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
int data_size = nthreads * 512;
|
||||
in.setRandom(data_size);
|
||||
out.setConstant(data_size, -1);
|
||||
cfin.setRandom(data_size);
|
||||
cfout.setConstant(data_size, -1);
|
||||
#endif
|
||||
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(coeff_wise<Vector3f>(), nthreads, in, out) );
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(coeff_wise<Array44f>(), nthreads, in, out) );
|
||||
|
||||
#if !defined(EIGEN_USE_HIP)
|
||||
// FIXME
|
||||
// These subtests result in a compile failure on the HIP platform
|
||||
//
|
||||
// eigen-upstream/Eigen/src/Core/Replicate.h:61:65: error:
|
||||
// base class 'internal::dense_xpr_base<Replicate<Array<float, 4, 1, 0, 4, 1>, -1, -1> >::type'
|
||||
// (aka 'ArrayBase<Eigen::Replicate<Eigen::Array<float, 4, 1, 0, 4, 1>, -1, -1> >') has protected default constructor
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(replicate<Array4f>(), nthreads, in, out) );
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(replicate<Array33f>(), nthreads, in, out) );
|
||||
|
||||
// HIP does not support new/delete on device.
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(alloc_new_delete<Vector3f>(), nthreads, in, out) );
|
||||
#endif
|
||||
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(redux<Array4f>(), nthreads, in, out) );
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(redux<Matrix3f>(), nthreads, in, out) );
|
||||
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(prod_test<Matrix3f,Matrix3f>(), nthreads, in, out) );
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(prod_test<Matrix4f,Vector4f>(), nthreads, in, out) );
|
||||
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(diagonal<Matrix3f,Vector3f>(), nthreads, in, out) );
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(diagonal<Matrix4f,Vector4f>(), nthreads, in, out) );
|
||||
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(matrix_inverse<Matrix2f>(), nthreads, in, out) );
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(matrix_inverse<Matrix3f>(), nthreads, in, out) );
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(matrix_inverse<Matrix4f>(), nthreads, in, out) );
|
||||
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(eigenvalues_direct<Matrix3f>(), nthreads, in, out) );
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(eigenvalues_direct<Matrix2f>(), nthreads, in, out) );
|
||||
|
||||
// Test std::complex.
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(complex_operators<Vector3cf>(), nthreads, cfin, cfout) );
|
||||
CALL_SUBTEST( test_with_infs_nans(complex_sqrt<Vector3cf>(), nthreads, cfin, cfout) );
|
||||
|
||||
// numeric_limits
|
||||
CALL_SUBTEST( test_with_infs_nans(numeric_limits_test<Vector3f>(), 1, in, out) );
|
||||
|
||||
#if defined(__NVCC__)
|
||||
// FIXME
|
||||
// These subtests compiles only with nvcc and fail with HIPCC and clang-cuda
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(eigenvalues<Matrix4f>(), nthreads, in, out) );
|
||||
typedef Matrix<float,6,6> Matrix6f;
|
||||
CALL_SUBTEST( run_and_compare_to_gpu(eigenvalues<Matrix6f>(), nthreads, in, out) );
|
||||
#endif
|
||||
}
|
||||
176
libs/eigen/test/gpu_common.h
Normal file
176
libs/eigen/test/gpu_common.h
Normal file
@@ -0,0 +1,176 @@
|
||||
#ifndef EIGEN_TEST_GPU_COMMON_H
|
||||
#define EIGEN_TEST_GPU_COMMON_H
|
||||
|
||||
#ifdef EIGEN_USE_HIP
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <hip/hip_runtime_api.h>
|
||||
#else
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <cuda_runtime_api.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define EIGEN_USE_GPU
|
||||
#include <unsupported/Eigen/CXX11/src/Tensor/TensorGpuHipCudaDefines.h>
|
||||
|
||||
#if !defined(__CUDACC__) && !defined(__HIPCC__)
|
||||
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__
|
||||
EIGEN_HIP_LAUNCH_BOUNDS_1024
|
||||
void run_on_gpu_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_gpu(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);
|
||||
|
||||
gpuMalloc((void**)(&d_in), in_bytes);
|
||||
gpuMalloc((void**)(&d_out), out_bytes);
|
||||
|
||||
gpuMemcpy(d_in, in.data(), in_bytes, gpuMemcpyHostToDevice);
|
||||
gpuMemcpy(d_out, out.data(), out_bytes, gpuMemcpyHostToDevice);
|
||||
|
||||
// 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) );
|
||||
|
||||
gpuDeviceSynchronize();
|
||||
|
||||
#ifdef EIGEN_USE_HIP
|
||||
hipLaunchKernelGGL(HIP_KERNEL_NAME(run_on_gpu_meta_kernel<Kernel,
|
||||
typename std::decay<decltype(*d_in)>::type,
|
||||
typename std::decay<decltype(*d_out)>::type>),
|
||||
dim3(Grids), dim3(Blocks), 0, 0, ker, n, d_in, d_out);
|
||||
#else
|
||||
run_on_gpu_meta_kernel<<<Grids,Blocks>>>(ker, n, d_in, d_out);
|
||||
#endif
|
||||
// Pre-launch errors.
|
||||
gpuError_t err = gpuGetLastError();
|
||||
if (err != gpuSuccess) {
|
||||
printf("%s: %s\n", gpuGetErrorName(err), gpuGetErrorString(err));
|
||||
gpu_assert(false);
|
||||
}
|
||||
|
||||
// Kernel execution errors.
|
||||
err = gpuDeviceSynchronize();
|
||||
if (err != gpuSuccess) {
|
||||
printf("%s: %s\n", gpuGetErrorName(err), gpuGetErrorString(err));
|
||||
gpu_assert(false);
|
||||
}
|
||||
|
||||
|
||||
// check inputs have not been modified
|
||||
gpuMemcpy(const_cast<typename Input::Scalar*>(in.data()), d_in, in_bytes, gpuMemcpyDeviceToHost);
|
||||
gpuMemcpy(out.data(), d_out, out_bytes, gpuMemcpyDeviceToHost);
|
||||
|
||||
gpuFree(d_in);
|
||||
gpuFree(d_out);
|
||||
}
|
||||
|
||||
|
||||
template<typename Kernel, typename Input, typename Output>
|
||||
void run_and_compare_to_gpu(const Kernel& ker, int n, const Input& in, Output& out)
|
||||
{
|
||||
Input in_ref, in_gpu;
|
||||
Output out_ref, out_gpu;
|
||||
#if !defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
in_ref = in_gpu = in;
|
||||
out_ref = out_gpu = out;
|
||||
#else
|
||||
EIGEN_UNUSED_VARIABLE(in);
|
||||
EIGEN_UNUSED_VARIABLE(out);
|
||||
#endif
|
||||
run_on_cpu (ker, n, in_ref, out_ref);
|
||||
run_on_gpu(ker, n, in_gpu, out_gpu);
|
||||
#if !defined(EIGEN_GPU_COMPILE_PHASE)
|
||||
VERIFY_IS_APPROX(in_ref, in_gpu);
|
||||
VERIFY_IS_APPROX(out_ref, out_gpu);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct compile_time_device_info {
|
||||
EIGEN_DEVICE_FUNC
|
||||
void operator()(int i, const int* /*in*/, int* info) const
|
||||
{
|
||||
if (i == 0) {
|
||||
EIGEN_UNUSED_VARIABLE(info)
|
||||
#if defined(__CUDA_ARCH__)
|
||||
info[0] = int(__CUDA_ARCH__ +0);
|
||||
#endif
|
||||
#if defined(EIGEN_HIP_DEVICE_COMPILE)
|
||||
info[1] = int(EIGEN_HIP_DEVICE_COMPILE +0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void ei_test_init_gpu()
|
||||
{
|
||||
int device = 0;
|
||||
gpuDeviceProp_t deviceProp;
|
||||
gpuGetDeviceProperties(&deviceProp, device);
|
||||
|
||||
ArrayXi dummy(1), info(10);
|
||||
info = -1;
|
||||
run_on_gpu(compile_time_device_info(),10,dummy,info);
|
||||
|
||||
|
||||
std::cout << "GPU compile-time info:\n";
|
||||
|
||||
#ifdef EIGEN_CUDACC
|
||||
std::cout << " EIGEN_CUDACC: " << int(EIGEN_CUDACC) << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_CUDA_SDK_VER
|
||||
std::cout << " EIGEN_CUDA_SDK_VER: " << int(EIGEN_CUDA_SDK_VER) << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_COMP_NVCC
|
||||
std::cout << " EIGEN_COMP_NVCC: " << int(EIGEN_COMP_NVCC) << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_HIPCC
|
||||
std::cout << " EIGEN_HIPCC: " << int(EIGEN_HIPCC) << "\n";
|
||||
#endif
|
||||
|
||||
std::cout << " EIGEN_CUDA_ARCH: " << info[0] << "\n";
|
||||
std::cout << " EIGEN_HIP_DEVICE_COMPILE: " << info[1] << "\n";
|
||||
|
||||
std::cout << "GPU 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_GPU_COMMON_H
|
||||
349
libs/eigen/test/half_float.cpp
Normal file
349
libs/eigen/test/half_float.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
// 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/Default/Half.h>
|
||||
|
||||
#define VERIFY_HALF_BITS_EQUAL(h, bits) \
|
||||
VERIFY_IS_EQUAL((numext::bit_cast<numext::uint16_t>(h)), (static_cast<numext::uint16_t>(bits)))
|
||||
|
||||
// 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_raw;
|
||||
|
||||
// Round-trip bit-cast with uint16.
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<half>(numext::bit_cast<numext::uint16_t>(half(1.0f))),
|
||||
half(1.0f));
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<half>(numext::bit_cast<numext::uint16_t>(half(0.5f))),
|
||||
half(0.5f));
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<half>(numext::bit_cast<numext::uint16_t>(half(-0.33333f))),
|
||||
half(-0.33333f));
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<half>(numext::bit_cast<numext::uint16_t>(half(0.0f))),
|
||||
half(0.0f));
|
||||
|
||||
// Conversion from float.
|
||||
VERIFY_HALF_BITS_EQUAL(half(1.0f), 0x3c00);
|
||||
VERIFY_HALF_BITS_EQUAL(half(0.5f), 0x3800);
|
||||
VERIFY_HALF_BITS_EQUAL(half(0.33333f), 0x3555);
|
||||
VERIFY_HALF_BITS_EQUAL(half(0.0f), 0x0000);
|
||||
VERIFY_HALF_BITS_EQUAL(half(-0.0f), 0x8000);
|
||||
VERIFY_HALF_BITS_EQUAL(half(65504.0f), 0x7bff);
|
||||
VERIFY_HALF_BITS_EQUAL(half(65536.0f), 0x7c00); // Becomes infinity.
|
||||
|
||||
// Denormals.
|
||||
VERIFY_HALF_BITS_EQUAL(half(-5.96046e-08f), 0x8001);
|
||||
VERIFY_HALF_BITS_EQUAL(half(5.96046e-08f), 0x0001);
|
||||
VERIFY_HALF_BITS_EQUAL(half(1.19209e-07f), 0x0002);
|
||||
|
||||
// Verify round-to-nearest-even behavior.
|
||||
float val1 = float(half(__half_raw(0x3c00)));
|
||||
float val2 = float(half(__half_raw(0x3c01)));
|
||||
float val3 = float(half(__half_raw(0x3c02)));
|
||||
VERIFY_HALF_BITS_EQUAL(half(0.5f * (val1 + val2)), 0x3c00);
|
||||
VERIFY_HALF_BITS_EQUAL(half(0.5f * (val2 + val3)), 0x3c02);
|
||||
|
||||
// Conversion from int.
|
||||
VERIFY_HALF_BITS_EQUAL(half(-1), 0xbc00);
|
||||
VERIFY_HALF_BITS_EQUAL(half(0), 0x0000);
|
||||
VERIFY_HALF_BITS_EQUAL(half(1), 0x3c00);
|
||||
VERIFY_HALF_BITS_EQUAL(half(2), 0x4000);
|
||||
VERIFY_HALF_BITS_EQUAL(half(3), 0x4200);
|
||||
|
||||
// Conversion from bool.
|
||||
VERIFY_HALF_BITS_EQUAL(half(false), 0x0000);
|
||||
VERIFY_HALF_BITS_EQUAL(half(true), 0x3c00);
|
||||
|
||||
// Conversion to float.
|
||||
VERIFY_IS_EQUAL(float(half(__half_raw(0x0000))), 0.0f);
|
||||
VERIFY_IS_EQUAL(float(half(__half_raw(0x3c00))), 1.0f);
|
||||
|
||||
// Denormals.
|
||||
VERIFY_IS_APPROX(float(half(__half_raw(0x8001))), -5.96046e-08f);
|
||||
VERIFY_IS_APPROX(float(half(__half_raw(0x0001))), 5.96046e-08f);
|
||||
VERIFY_IS_APPROX(float(half(__half_raw(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_raw(0xfc00)))));
|
||||
VERIFY((numext::isnan)(float(half(__half_raw(0xfc01)))));
|
||||
VERIFY((numext::isinf)(float(half(__half_raw(0x7c00)))));
|
||||
VERIFY((numext::isnan)(float(half(__half_raw(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_raw(0x7bff))));
|
||||
VERIFY(!(numext::isnan)(half(__half_raw(0x0000))));
|
||||
VERIFY((numext::isinf)(half(__half_raw(0xfc00))));
|
||||
VERIFY((numext::isnan)(half(__half_raw(0xfc01))));
|
||||
VERIFY((numext::isinf)(half(__half_raw(0x7c00))));
|
||||
VERIFY((numext::isnan)(half(__half_raw(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
|
||||
|
||||
// Conversion to bool
|
||||
VERIFY(!static_cast<bool>(half(0.0)));
|
||||
VERIFY(!static_cast<bool>(half(-0.0)));
|
||||
VERIFY(static_cast<bool>(half(__half_raw(0x7bff))));
|
||||
VERIFY(static_cast<bool>(half(-0.33333)));
|
||||
VERIFY(static_cast<bool>(half(1.0)));
|
||||
VERIFY(static_cast<bool>(half(-1.0)));
|
||||
VERIFY(static_cast<bool>(half(-5.96046e-08f)));
|
||||
}
|
||||
|
||||
void test_numtraits()
|
||||
{
|
||||
std::cout << "epsilon = " << NumTraits<half>::epsilon() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<half>::epsilon()) << ")" << std::endl;
|
||||
std::cout << "highest = " << NumTraits<half>::highest() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<half>::highest()) << ")" << std::endl;
|
||||
std::cout << "lowest = " << NumTraits<half>::lowest() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<half>::lowest()) << ")" << std::endl;
|
||||
std::cout << "min = " << (std::numeric_limits<half>::min)() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(half((std::numeric_limits<half>::min)())) << ")" << std::endl;
|
||||
std::cout << "denorm min = " << (std::numeric_limits<half>::denorm_min)() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(half((std::numeric_limits<half>::denorm_min)())) << ")" << std::endl;
|
||||
std::cout << "infinity = " << NumTraits<half>::infinity() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<half>::infinity()) << ")" << std::endl;
|
||||
std::cout << "quiet nan = " << NumTraits<half>::quiet_NaN() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(NumTraits<half>::quiet_NaN()) << ")" << std::endl;
|
||||
std::cout << "signaling nan = " << std::numeric_limits<half>::signaling_NaN() << " (0x" << std::hex << numext::bit_cast<numext::uint16_t>(std::numeric_limits<half>::signaling_NaN()) << ")" << std::endl;
|
||||
|
||||
VERIFY(NumTraits<half>::IsSigned);
|
||||
|
||||
VERIFY_IS_EQUAL(
|
||||
numext::bit_cast<numext::uint16_t>(std::numeric_limits<half>::infinity()),
|
||||
numext::bit_cast<numext::uint16_t>(half(std::numeric_limits<float>::infinity())) );
|
||||
// There is no guarantee that casting a 32-bit NaN to 16-bit has a precise
|
||||
// bit pattern. We test that it is in fact a NaN, then test the signaling
|
||||
// bit (msb of significand is 1 for quiet, 0 for signaling).
|
||||
const numext::uint16_t HALF_QUIET_BIT = 0x0200;
|
||||
VERIFY(
|
||||
(numext::isnan)(std::numeric_limits<half>::quiet_NaN())
|
||||
&& (numext::isnan)(half(std::numeric_limits<float>::quiet_NaN()))
|
||||
&& ((numext::bit_cast<numext::uint16_t>(std::numeric_limits<half>::quiet_NaN()) & HALF_QUIET_BIT) > 0)
|
||||
&& ((numext::bit_cast<numext::uint16_t>(half(std::numeric_limits<float>::quiet_NaN())) & HALF_QUIET_BIT) > 0) );
|
||||
// After a cast to half, a signaling NaN may become non-signaling
|
||||
// (e.g. in the case of casting float to native __fp16). Thus, we check that
|
||||
// both are NaN, and that only the `numeric_limits` version is signaling.
|
||||
VERIFY(
|
||||
(numext::isnan)(std::numeric_limits<half>::signaling_NaN())
|
||||
&& (numext::isnan)(half(std::numeric_limits<float>::signaling_NaN()))
|
||||
&& ((numext::bit_cast<numext::uint16_t>(std::numeric_limits<half>::signaling_NaN()) & HALF_QUIET_BIT) == 0) );
|
||||
|
||||
VERIFY( (std::numeric_limits<half>::min)() > half(0.f) );
|
||||
VERIFY( (std::numeric_limits<half>::denorm_min)() > half(0.f) );
|
||||
VERIFY( (std::numeric_limits<half>::min)()/half(2) > half(0.f) );
|
||||
VERIFY_IS_EQUAL( (std::numeric_limits<half>::denorm_min)()/half(2), half(0.f) );
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
half x(3);
|
||||
half y = ++x;
|
||||
VERIFY_IS_EQUAL(x, half(4));
|
||||
VERIFY_IS_EQUAL(y, half(4));
|
||||
y = --x;
|
||||
VERIFY_IS_EQUAL(x, half(3));
|
||||
VERIFY_IS_EQUAL(y, half(3));
|
||||
y = x++;
|
||||
VERIFY_IS_EQUAL(x, half(4));
|
||||
VERIFY_IS_EQUAL(y, half(3));
|
||||
y = x--;
|
||||
VERIFY_IS_EQUAL(x, half(3));
|
||||
VERIFY_IS_EQUAL(y, half(4));
|
||||
}
|
||||
|
||||
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::expm1(half(0.0f))), 0.0f);
|
||||
VERIFY_IS_EQUAL(float(expm1(half(0.0f))), 0.0f);
|
||||
VERIFY_IS_APPROX(float(numext::expm1(half(2.0f))), 6.3890561f);
|
||||
VERIFY_IS_APPROX(float(expm1(half(2.0f))), 6.3890561f);
|
||||
|
||||
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);
|
||||
|
||||
VERIFY_IS_APPROX(numext::fmod(half(5.3f), half(2.0f)), half(1.3f));
|
||||
VERIFY_IS_APPROX(fmod(half(5.3f), half(2.0f)), half(1.3f));
|
||||
VERIFY_IS_APPROX(numext::fmod(half(-18.5f), half(-4.2f)), half(-1.7f));
|
||||
VERIFY_IS_APPROX(fmod(half(-18.5f), half(-4.2f)), half(-1.7f));
|
||||
}
|
||||
|
||||
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_product()
|
||||
{
|
||||
typedef Matrix<half,Dynamic,Dynamic> MatrixXh;
|
||||
Index rows = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
Index cols = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
Index depth = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
MatrixXh Ah = MatrixXh::Random(rows,depth);
|
||||
MatrixXh Bh = MatrixXh::Random(depth,cols);
|
||||
MatrixXh Ch = MatrixXh::Random(rows,cols);
|
||||
MatrixXf Af = Ah.cast<float>();
|
||||
MatrixXf Bf = Bh.cast<float>();
|
||||
MatrixXf Cf = Ch.cast<float>();
|
||||
VERIFY_IS_APPROX(Ch.noalias()+=Ah*Bh, (Cf.noalias()+=Af*Bf).cast<half>());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(half_float)
|
||||
{
|
||||
CALL_SUBTEST(test_numtraits());
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST(test_conversion());
|
||||
CALL_SUBTEST(test_arithmetic());
|
||||
CALL_SUBTEST(test_comparison());
|
||||
CALL_SUBTEST(test_basic_functions());
|
||||
CALL_SUBTEST(test_trigonometric_functions());
|
||||
CALL_SUBTEST(test_array());
|
||||
CALL_SUBTEST(test_product());
|
||||
}
|
||||
}
|
||||
62
libs/eigen/test/hessenberg.cpp
Normal file
62
libs/eigen/test/hessenberg.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
|
||||
//
|
||||
// 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/Eigenvalues>
|
||||
|
||||
template<typename Scalar,int Size> void hessenberg(int size = Size)
|
||||
{
|
||||
typedef Matrix<Scalar,Size,Size> MatrixType;
|
||||
|
||||
// Test basic functionality: A = U H U* and H is Hessenberg
|
||||
for(int counter = 0; counter < g_repeat; ++counter) {
|
||||
MatrixType m = MatrixType::Random(size,size);
|
||||
HessenbergDecomposition<MatrixType> hess(m);
|
||||
MatrixType Q = hess.matrixQ();
|
||||
MatrixType H = hess.matrixH();
|
||||
VERIFY_IS_APPROX(m, Q * H * Q.adjoint());
|
||||
for(int row = 2; row < size; ++row) {
|
||||
for(int col = 0; col < row-1; ++col) {
|
||||
VERIFY(H(row,col) == (typename MatrixType::Scalar)0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test whether compute() and constructor returns same result
|
||||
MatrixType A = MatrixType::Random(size, size);
|
||||
HessenbergDecomposition<MatrixType> cs1;
|
||||
cs1.compute(A);
|
||||
HessenbergDecomposition<MatrixType> cs2(A);
|
||||
VERIFY_IS_EQUAL(cs1.matrixH().eval(), cs2.matrixH().eval());
|
||||
MatrixType cs1Q = cs1.matrixQ();
|
||||
MatrixType cs2Q = cs2.matrixQ();
|
||||
VERIFY_IS_EQUAL(cs1Q, cs2Q);
|
||||
|
||||
// Test assertions for when used uninitialized
|
||||
HessenbergDecomposition<MatrixType> hessUninitialized;
|
||||
VERIFY_RAISES_ASSERT( hessUninitialized.matrixH() );
|
||||
VERIFY_RAISES_ASSERT( hessUninitialized.matrixQ() );
|
||||
VERIFY_RAISES_ASSERT( hessUninitialized.householderCoefficients() );
|
||||
VERIFY_RAISES_ASSERT( hessUninitialized.packedMatrix() );
|
||||
|
||||
// TODO: Add tests for packedMatrix() and householderCoefficients()
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(hessenberg)
|
||||
{
|
||||
CALL_SUBTEST_1(( hessenberg<std::complex<double>,1>() ));
|
||||
CALL_SUBTEST_2(( hessenberg<std::complex<double>,2>() ));
|
||||
CALL_SUBTEST_3(( hessenberg<std::complex<float>,4>() ));
|
||||
CALL_SUBTEST_4(( hessenberg<float,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
|
||||
CALL_SUBTEST_5(( hessenberg<std::complex<double>,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
|
||||
|
||||
// Test problem size constructors
|
||||
CALL_SUBTEST_6(HessenbergDecomposition<MatrixXf>(10));
|
||||
}
|
||||
148
libs/eigen/test/householder.cpp
Normal file
148
libs/eigen/test/householder.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009-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"
|
||||
#include <Eigen/QR>
|
||||
|
||||
template<typename MatrixType> void householder(const MatrixType& m)
|
||||
{
|
||||
static bool even = true;
|
||||
even = !even;
|
||||
/* this test covers the following files:
|
||||
Householder.h
|
||||
*/
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
typedef Matrix<Scalar, internal::decrement_size<MatrixType::RowsAtCompileTime>::ret, 1> EssentialVectorType;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
|
||||
typedef Matrix<Scalar, Dynamic, MatrixType::ColsAtCompileTime> HBlockMatrixType;
|
||||
typedef Matrix<Scalar, Dynamic, 1> HCoeffsVectorType;
|
||||
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime> TMatrixType;
|
||||
|
||||
Matrix<Scalar, EIGEN_SIZE_MAX(MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime), 1> _tmp((std::max)(rows,cols));
|
||||
Scalar* tmp = &_tmp.coeffRef(0,0);
|
||||
|
||||
Scalar beta;
|
||||
RealScalar alpha;
|
||||
EssentialVectorType essential;
|
||||
|
||||
VectorType v1 = VectorType::Random(rows), v2;
|
||||
v2 = v1;
|
||||
v1.makeHouseholder(essential, beta, alpha);
|
||||
v1.applyHouseholderOnTheLeft(essential,beta,tmp);
|
||||
VERIFY_IS_APPROX(v1.norm(), v2.norm());
|
||||
if(rows>=2) VERIFY_IS_MUCH_SMALLER_THAN(v1.tail(rows-1).norm(), v1.norm());
|
||||
v1 = VectorType::Random(rows);
|
||||
v2 = v1;
|
||||
v1.applyHouseholderOnTheLeft(essential,beta,tmp);
|
||||
VERIFY_IS_APPROX(v1.norm(), v2.norm());
|
||||
|
||||
// reconstruct householder matrix:
|
||||
SquareMatrixType id, H1, H2;
|
||||
id.setIdentity(rows, rows);
|
||||
H1 = H2 = id;
|
||||
VectorType vv(rows);
|
||||
vv << Scalar(1), essential;
|
||||
H1.applyHouseholderOnTheLeft(essential, beta, tmp);
|
||||
H2.applyHouseholderOnTheRight(essential, beta, tmp);
|
||||
VERIFY_IS_APPROX(H1, H2);
|
||||
VERIFY_IS_APPROX(H1, id - beta * vv*vv.adjoint());
|
||||
|
||||
MatrixType m1(rows, cols),
|
||||
m2(rows, cols);
|
||||
|
||||
v1 = VectorType::Random(rows);
|
||||
if(even) v1.tail(rows-1).setZero();
|
||||
m1.colwise() = v1;
|
||||
m2 = m1;
|
||||
m1.col(0).makeHouseholder(essential, beta, alpha);
|
||||
m1.applyHouseholderOnTheLeft(essential,beta,tmp);
|
||||
VERIFY_IS_APPROX(m1.norm(), m2.norm());
|
||||
if(rows>=2) VERIFY_IS_MUCH_SMALLER_THAN(m1.block(1,0,rows-1,cols).norm(), m1.norm());
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(numext::imag(m1(0,0)), numext::real(m1(0,0)));
|
||||
VERIFY_IS_APPROX(numext::real(m1(0,0)), alpha);
|
||||
|
||||
v1 = VectorType::Random(rows);
|
||||
if(even) v1.tail(rows-1).setZero();
|
||||
SquareMatrixType m3(rows,rows), m4(rows,rows);
|
||||
m3.rowwise() = v1.transpose();
|
||||
m4 = m3;
|
||||
m3.row(0).makeHouseholder(essential, beta, alpha);
|
||||
m3.applyHouseholderOnTheRight(essential.conjugate(),beta,tmp);
|
||||
VERIFY_IS_APPROX(m3.norm(), m4.norm());
|
||||
if(rows>=2) VERIFY_IS_MUCH_SMALLER_THAN(m3.block(0,1,rows,rows-1).norm(), m3.norm());
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(numext::imag(m3(0,0)), numext::real(m3(0,0)));
|
||||
VERIFY_IS_APPROX(numext::real(m3(0,0)), alpha);
|
||||
|
||||
// test householder sequence on the left with a shift
|
||||
|
||||
Index shift = internal::random<Index>(0, std::max<Index>(rows-2,0));
|
||||
Index brows = rows - shift;
|
||||
m1.setRandom(rows, cols);
|
||||
HBlockMatrixType hbm = m1.block(shift,0,brows,cols);
|
||||
HouseholderQR<HBlockMatrixType> qr(hbm);
|
||||
m2 = m1;
|
||||
m2.block(shift,0,brows,cols) = qr.matrixQR();
|
||||
HCoeffsVectorType hc = qr.hCoeffs().conjugate();
|
||||
HouseholderSequence<MatrixType, HCoeffsVectorType> hseq(m2, hc);
|
||||
hseq.setLength(hc.size()).setShift(shift);
|
||||
VERIFY(hseq.length() == hc.size());
|
||||
VERIFY(hseq.shift() == shift);
|
||||
|
||||
MatrixType m5 = m2;
|
||||
m5.block(shift,0,brows,cols).template triangularView<StrictlyLower>().setZero();
|
||||
VERIFY_IS_APPROX(hseq * m5, m1); // test applying hseq directly
|
||||
m3 = hseq;
|
||||
VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating hseq to a dense matrix, then applying
|
||||
|
||||
SquareMatrixType hseq_mat = hseq;
|
||||
SquareMatrixType hseq_mat_conj = hseq.conjugate();
|
||||
SquareMatrixType hseq_mat_adj = hseq.adjoint();
|
||||
SquareMatrixType hseq_mat_trans = hseq.transpose();
|
||||
SquareMatrixType m6 = SquareMatrixType::Random(rows, rows);
|
||||
VERIFY_IS_APPROX(hseq_mat.adjoint(), hseq_mat_adj);
|
||||
VERIFY_IS_APPROX(hseq_mat.conjugate(), hseq_mat_conj);
|
||||
VERIFY_IS_APPROX(hseq_mat.transpose(), hseq_mat_trans);
|
||||
VERIFY_IS_APPROX(hseq * m6, hseq_mat * m6);
|
||||
VERIFY_IS_APPROX(hseq.adjoint() * m6, hseq_mat_adj * m6);
|
||||
VERIFY_IS_APPROX(hseq.conjugate() * m6, hseq_mat_conj * m6);
|
||||
VERIFY_IS_APPROX(hseq.transpose() * m6, hseq_mat_trans * m6);
|
||||
VERIFY_IS_APPROX(m6 * hseq, m6 * hseq_mat);
|
||||
VERIFY_IS_APPROX(m6 * hseq.adjoint(), m6 * hseq_mat_adj);
|
||||
VERIFY_IS_APPROX(m6 * hseq.conjugate(), m6 * hseq_mat_conj);
|
||||
VERIFY_IS_APPROX(m6 * hseq.transpose(), m6 * hseq_mat_trans);
|
||||
|
||||
// test householder sequence on the right with a shift
|
||||
|
||||
TMatrixType tm2 = m2.transpose();
|
||||
HouseholderSequence<TMatrixType, HCoeffsVectorType, OnTheRight> rhseq(tm2, hc);
|
||||
rhseq.setLength(hc.size()).setShift(shift);
|
||||
VERIFY_IS_APPROX(rhseq * m5, m1); // test applying rhseq directly
|
||||
m3 = rhseq;
|
||||
VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating rhseq to a dense matrix, then applying
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(householder)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( householder(Matrix<double,2,2>()) );
|
||||
CALL_SUBTEST_2( householder(Matrix<float,2,3>()) );
|
||||
CALL_SUBTEST_3( householder(Matrix<double,3,5>()) );
|
||||
CALL_SUBTEST_4( householder(Matrix<float,4,4>()) );
|
||||
CALL_SUBTEST_5( householder(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_6( householder(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_7( householder(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_8( householder(Matrix<double,1,1>()) );
|
||||
}
|
||||
}
|
||||
69
libs/eigen/test/incomplete_cholesky.cpp
Normal file
69
libs/eigen/test/incomplete_cholesky.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
// 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) );
|
||||
}
|
||||
|
||||
template<int>
|
||||
void bug1150()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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>() ));
|
||||
|
||||
CALL_SUBTEST_1(( bug1150<0>() ));
|
||||
}
|
||||
473
libs/eigen/test/indexed_view.cpp
Normal file
473
libs/eigen/test/indexed_view.cpp
Normal file
@@ -0,0 +1,473 @@
|
||||
// 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/.
|
||||
|
||||
#ifdef EIGEN_TEST_PART_2
|
||||
// Make sure we also check c++11 max implementation
|
||||
#define EIGEN_MAX_CPP_VER 11
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_TEST_PART_3
|
||||
// Make sure we also check c++98 max implementation
|
||||
#define EIGEN_MAX_CPP_VER 03
|
||||
|
||||
// We need to disable this warning when compiling with c++11 while limiting Eigen to c++98
|
||||
// Ideally we would rather configure the compiler to build in c++98 mode but this needs
|
||||
// to be done at the CMakeLists.txt level.
|
||||
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >=9)
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-copy"
|
||||
#endif
|
||||
#if defined(__clang__) && (__clang_major__ >= 10)
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-copy"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <valarray>
|
||||
#include <vector>
|
||||
#include "main.h"
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
typedef std::pair<Index,Index> IndexPair;
|
||||
|
||||
int encode(Index i, Index j) {
|
||||
return int(i*100 + j);
|
||||
}
|
||||
|
||||
IndexPair decode(Index ij) {
|
||||
return IndexPair(ij / 100, ij % 100);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool match(const T& xpr, std::string ref, std::string str_xpr = "") {
|
||||
EIGEN_UNUSED_VARIABLE(str_xpr);
|
||||
std::stringstream str;
|
||||
str << xpr;
|
||||
if(!(str.str() == ref))
|
||||
std::cout << str_xpr << "\n" << xpr << "\n\n";
|
||||
return str.str() == ref;
|
||||
}
|
||||
|
||||
#define MATCH(X,R) match(X, R, #X)
|
||||
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_eq(const T1& a, const T2& b)
|
||||
{
|
||||
return (a == b).all();
|
||||
}
|
||||
|
||||
template<typename T1,typename T2>
|
||||
bool is_same_seq(const T1& a, const T2& b)
|
||||
{
|
||||
bool ok = a.first()==b.first() && a.size() == b.size() && Index(a.incrObject())==Index(b.incrObject());;
|
||||
if(!ok)
|
||||
{
|
||||
std::cerr << "seqN(" << a.first() << ", " << a.size() << ", " << Index(a.incrObject()) << ") != ";
|
||||
std::cerr << "seqN(" << b.first() << ", " << b.size() << ", " << Index(b.incrObject()) << ")\n";
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_seq_type(const T1& a, const T2& b)
|
||||
{
|
||||
return is_same_seq(a,b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define VERIFY_EQ_INT(A,B) VERIFY_IS_APPROX(int(A),int(B))
|
||||
|
||||
// C++03 does not allow local or unnamed enums as index
|
||||
enum DummyEnum { XX=0, YY=1 };
|
||||
|
||||
void check_indexed_view()
|
||||
{
|
||||
Index n = 10;
|
||||
|
||||
ArrayXd a = ArrayXd::LinSpaced(n,0,n-1);
|
||||
Array<double,1,Dynamic> b = a.transpose();
|
||||
|
||||
#if EIGEN_COMP_CXXVER>=14
|
||||
ArrayXXi A = ArrayXXi::NullaryExpr(n,n, std::ref(encode));
|
||||
#else
|
||||
ArrayXXi A = ArrayXXi::NullaryExpr(n,n, std::ptr_fun(&encode));
|
||||
#endif
|
||||
|
||||
for(Index i=0; i<n; ++i)
|
||||
for(Index j=0; j<n; ++j)
|
||||
VERIFY( decode(A(i,j)) == IndexPair(i,j) );
|
||||
|
||||
Array4i eii(4); eii << 3, 1, 6, 5;
|
||||
std::valarray<int> vali(4); Map<ArrayXi>(&vali[0],4) = eii;
|
||||
std::vector<int> veci(4); Map<ArrayXi>(veci.data(),4) = eii;
|
||||
|
||||
VERIFY( MATCH( A(3, seq(9,3,-1)),
|
||||
"309 308 307 306 305 304 303")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(seqN(2,5), seq(9,3,-1)),
|
||||
"209 208 207 206 205 204 203\n"
|
||||
"309 308 307 306 305 304 303\n"
|
||||
"409 408 407 406 405 404 403\n"
|
||||
"509 508 507 506 505 504 503\n"
|
||||
"609 608 607 606 605 604 603")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(seqN(2,5), 5),
|
||||
"205\n"
|
||||
"305\n"
|
||||
"405\n"
|
||||
"505\n"
|
||||
"605")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(seqN(last,5,-1), seq(2,last)),
|
||||
"902 903 904 905 906 907 908 909\n"
|
||||
"802 803 804 805 806 807 808 809\n"
|
||||
"702 703 704 705 706 707 708 709\n"
|
||||
"602 603 604 605 606 607 608 609\n"
|
||||
"502 503 504 505 506 507 508 509")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(eii, veci),
|
||||
"303 301 306 305\n"
|
||||
"103 101 106 105\n"
|
||||
"603 601 606 605\n"
|
||||
"503 501 506 505")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( A(eii, all),
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"100 101 102 103 104 105 106 107 108 109\n"
|
||||
"600 601 602 603 604 605 606 607 608 609\n"
|
||||
"500 501 502 503 504 505 506 507 508 509")
|
||||
);
|
||||
|
||||
// take row number 3, and repeat it 5 times
|
||||
VERIFY( MATCH( A(seqN(3,5,0), all),
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"300 301 302 303 304 305 306 307 308 309\n"
|
||||
"300 301 302 303 304 305 306 307 308 309")
|
||||
);
|
||||
|
||||
VERIFY( MATCH( a(seqN(3,3),0), "3\n4\n5" ) );
|
||||
VERIFY( MATCH( a(seq(3,5)), "3\n4\n5" ) );
|
||||
VERIFY( MATCH( a(seqN(3,3,1)), "3\n4\n5" ) );
|
||||
VERIFY( MATCH( a(seqN(5,3,-1)), "5\n4\n3" ) );
|
||||
|
||||
VERIFY( MATCH( b(0,seqN(3,3)), "3 4 5" ) );
|
||||
VERIFY( MATCH( b(seq(3,5)), "3 4 5" ) );
|
||||
VERIFY( MATCH( b(seqN(3,3,1)), "3 4 5" ) );
|
||||
VERIFY( MATCH( b(seqN(5,3,-1)), "5 4 3" ) );
|
||||
|
||||
VERIFY( MATCH( b(all), "0 1 2 3 4 5 6 7 8 9" ) );
|
||||
VERIFY( MATCH( b(eii), "3 1 6 5" ) );
|
||||
|
||||
Array44i B;
|
||||
B.setRandom();
|
||||
VERIFY( (A(seqN(2,5), 5)).ColsAtCompileTime == 1);
|
||||
VERIFY( (A(seqN(2,5), 5)).RowsAtCompileTime == Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5), 5)).InnerStrideAtCompileTime , A.InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5), 5)).OuterStrideAtCompileTime , A.col(5).OuterStrideAtCompileTime);
|
||||
|
||||
VERIFY_EQ_INT( (A(5,seqN(2,5))).InnerStrideAtCompileTime , A.row(5).InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (A(5,seqN(2,5))).OuterStrideAtCompileTime , A.row(5).OuterStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (B(1,seqN(1,2))).InnerStrideAtCompileTime , B.row(1).InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (B(1,seqN(1,2))).OuterStrideAtCompileTime , B.row(1).OuterStrideAtCompileTime);
|
||||
|
||||
VERIFY_EQ_INT( (A(seqN(2,5), seq(1,3))).InnerStrideAtCompileTime , A.InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5), seq(1,3))).OuterStrideAtCompileTime , A.OuterStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (B(seqN(1,2), seq(1,3))).InnerStrideAtCompileTime , B.InnerStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (B(seqN(1,2), seq(1,3))).OuterStrideAtCompileTime , B.OuterStrideAtCompileTime);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5,2), seq(1,3,2))).InnerStrideAtCompileTime , Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5,2), seq(1,3,2))).OuterStrideAtCompileTime , Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5,fix<2>), seq(1,3,fix<3>))).InnerStrideAtCompileTime , 2);
|
||||
VERIFY_EQ_INT( (A(seqN(2,5,fix<2>), seq(1,3,fix<3>))).OuterStrideAtCompileTime , Dynamic);
|
||||
VERIFY_EQ_INT( (B(seqN(1,2,fix<2>), seq(1,3,fix<3>))).InnerStrideAtCompileTime , 2);
|
||||
VERIFY_EQ_INT( (B(seqN(1,2,fix<2>), seq(1,3,fix<3>))).OuterStrideAtCompileTime , 3*4);
|
||||
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<5>), seqN(1,fix<3>))).RowsAtCompileTime, 5);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<5>), seqN(1,fix<3>))).ColsAtCompileTime, 3);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<5>(5)), seqN(1,fix<3>(3)))).RowsAtCompileTime, 5);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<5>(5)), seqN(1,fix<3>(3)))).ColsAtCompileTime, 3);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<Dynamic>(5)), seqN(1,fix<Dynamic>(3)))).RowsAtCompileTime, Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<Dynamic>(5)), seqN(1,fix<Dynamic>(3)))).ColsAtCompileTime, Dynamic);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<Dynamic>(5)), seqN(1,fix<Dynamic>(3)))).rows(), 5);
|
||||
VERIFY_EQ_INT( (A(seqN(2,fix<Dynamic>(5)), seqN(1,fix<Dynamic>(3)))).cols(), 3);
|
||||
|
||||
VERIFY( is_same_seq_type( seqN(2,5,fix<-1>), seqN(2,5,fix<-1>(-1)) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,5), seqN(2,5,fix<1>(1)) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,5,3), seqN(2,5,fix<DynamicIndex>(3)) ) );
|
||||
VERIFY( is_same_seq_type( seq(2,7,fix<3>), seqN(2,2,fix<3>) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,fix<Dynamic>(5),3), seqN(2,5,fix<DynamicIndex>(3)) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,fix<5>(5),fix<-2>), seqN(2,fix<5>,fix<-2>()) ) );
|
||||
|
||||
VERIFY( is_same_seq_type( seq(2,fix<5>), seqN(2,4) ) );
|
||||
#if EIGEN_HAS_CXX11
|
||||
VERIFY( is_same_seq_type( seq(fix<2>,fix<5>), seqN(fix<2>,fix<4>) ) );
|
||||
VERIFY( is_same_seq( seqN(2,std::integral_constant<int,5>(),std::integral_constant<int,-2>()), seqN(2,fix<5>,fix<-2>()) ) );
|
||||
VERIFY( is_same_seq( seq(std::integral_constant<int,1>(),std::integral_constant<int,5>(),std::integral_constant<int,2>()),
|
||||
seq(fix<1>,fix<5>,fix<2>()) ) );
|
||||
VERIFY( is_same_seq_type( seqN(2,std::integral_constant<int,5>(),std::integral_constant<int,-2>()), seqN(2,fix<5>,fix<-2>()) ) );
|
||||
VERIFY( is_same_seq_type( seq(std::integral_constant<int,1>(),std::integral_constant<int,5>(),std::integral_constant<int,2>()),
|
||||
seq(fix<1>,fix<5>,fix<2>()) ) );
|
||||
|
||||
VERIFY( is_same_seq_type( seqN(2,std::integral_constant<int,5>()), seqN(2,fix<5>) ) );
|
||||
VERIFY( is_same_seq_type( seq(std::integral_constant<int,1>(),std::integral_constant<int,5>()), seq(fix<1>,fix<5>) ) );
|
||||
#else
|
||||
// sorry, no compile-time size recovery in c++98/03
|
||||
VERIFY( is_same_seq( seq(fix<2>,fix<5>), seqN(fix<2>,fix<4>) ) );
|
||||
#endif
|
||||
|
||||
VERIFY( (A(seqN(2,fix<5>), 5)).RowsAtCompileTime == 5);
|
||||
VERIFY( (A(4, all)).ColsAtCompileTime == Dynamic);
|
||||
VERIFY( (A(4, all)).RowsAtCompileTime == 1);
|
||||
VERIFY( (B(1, all)).ColsAtCompileTime == 4);
|
||||
VERIFY( (B(1, all)).RowsAtCompileTime == 1);
|
||||
VERIFY( (B(all,1)).ColsAtCompileTime == 1);
|
||||
VERIFY( (B(all,1)).RowsAtCompileTime == 4);
|
||||
|
||||
VERIFY(int( (A(all, eii)).ColsAtCompileTime) == int(eii.SizeAtCompileTime));
|
||||
VERIFY_EQ_INT( (A(eii, eii)).Flags&DirectAccessBit, (unsigned int)(0));
|
||||
VERIFY_EQ_INT( (A(eii, eii)).InnerStrideAtCompileTime, 0);
|
||||
VERIFY_EQ_INT( (A(eii, eii)).OuterStrideAtCompileTime, 0);
|
||||
|
||||
VERIFY_IS_APPROX( A(seq(n-1,2,-2), seqN(n-1-6,3,-1)), A(seq(last,2,fix<-2>), seqN(last-6,3,fix<-1>)) );
|
||||
|
||||
VERIFY_IS_APPROX( A(seq(n-1,2,-2), seqN(n-1-6,4)), A(seq(last,2,-2), seqN(last-6,4)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-1-6,n-1-2), seqN(n-1-6,4)), A(seq(last-6,last-2), seqN(6+last-6-6,4)) );
|
||||
VERIFY_IS_APPROX( A(seq((n-1)/2,(n)/2+3), seqN(2,4)), A(seq(last/2,(last+1)/2+3), seqN(last+2-last,4)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-2,2,-2), seqN(n-8,4)), A(seq(lastp1-2,2,-2), seqN(lastp1-8,4)) );
|
||||
|
||||
// Check all combinations of seq:
|
||||
VERIFY_IS_APPROX( A(seq(1,n-1-2,2), seq(1,n-1-2,2)), A(seq(1,last-2,2), seq(1,last-2,fix<2>)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-1-5,n-1-2,2), seq(n-1-5,n-1-2,2)), A(seq(last-5,last-2,2), seq(last-5,last-2,fix<2>)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-1-5,7,2), seq(n-1-5,7,2)), A(seq(last-5,7,2), seq(last-5,7,fix<2>)) );
|
||||
VERIFY_IS_APPROX( A(seq(1,n-1-2), seq(n-1-5,7)), A(seq(1,last-2), seq(last-5,7)) );
|
||||
VERIFY_IS_APPROX( A(seq(n-1-5,n-1-2), seq(n-1-5,n-1-2)), A(seq(last-5,last-2), seq(last-5,last-2)) );
|
||||
|
||||
VERIFY_IS_APPROX( A.col(A.cols()-1), A(all,last) );
|
||||
VERIFY_IS_APPROX( A(A.rows()-2, A.cols()/2), A(last-1, lastp1/2) );
|
||||
VERIFY_IS_APPROX( a(a.size()-2), a(last-1) );
|
||||
VERIFY_IS_APPROX( a(a.size()/2), a((last+1)/2) );
|
||||
|
||||
// Check fall-back to Block
|
||||
{
|
||||
VERIFY( is_same_eq(A.col(0), A(all,0)) );
|
||||
VERIFY( is_same_eq(A.row(0), A(0,all)) );
|
||||
VERIFY( is_same_eq(A.block(0,0,2,2), A(seqN(0,2),seq(0,1))) );
|
||||
VERIFY( is_same_eq(A.middleRows(2,4), A(seqN(2,4),all)) );
|
||||
VERIFY( is_same_eq(A.middleCols(2,4), A(all,seqN(2,4))) );
|
||||
|
||||
VERIFY( is_same_eq(A.col(A.cols()-1), A(all,last)) );
|
||||
|
||||
const ArrayXXi& cA(A);
|
||||
VERIFY( is_same_eq(cA.col(0), cA(all,0)) );
|
||||
VERIFY( is_same_eq(cA.row(0), cA(0,all)) );
|
||||
VERIFY( is_same_eq(cA.block(0,0,2,2), cA(seqN(0,2),seq(0,1))) );
|
||||
VERIFY( is_same_eq(cA.middleRows(2,4), cA(seqN(2,4),all)) );
|
||||
VERIFY( is_same_eq(cA.middleCols(2,4), cA(all,seqN(2,4))) );
|
||||
|
||||
VERIFY( is_same_eq(a.head(4), a(seq(0,3))) );
|
||||
VERIFY( is_same_eq(a.tail(4), a(seqN(last-3,4))) );
|
||||
VERIFY( is_same_eq(a.tail(4), a(seq(lastp1-4,last))) );
|
||||
VERIFY( is_same_eq(a.segment<4>(3), a(seqN(3,fix<4>))) );
|
||||
}
|
||||
|
||||
ArrayXXi A1=A, A2 = ArrayXXi::Random(4,4);
|
||||
ArrayXi range25(4); range25 << 3,2,4,5;
|
||||
A1(seqN(3,4),seq(2,5)) = A2;
|
||||
VERIFY_IS_APPROX( A1.block(3,2,4,4), A2 );
|
||||
A1 = A;
|
||||
A2.setOnes();
|
||||
A1(seq(6,3,-1),range25) = A2;
|
||||
VERIFY_IS_APPROX( A1.block(3,2,4,4), A2 );
|
||||
|
||||
// check reverse
|
||||
{
|
||||
VERIFY( is_same_seq_type( seq(3,7).reverse(), seqN(7,5,fix<-1>) ) );
|
||||
VERIFY( is_same_seq_type( seq(7,3,fix<-2>).reverse(), seqN(3,3,fix<2>) ) );
|
||||
VERIFY_IS_APPROX( a(seqN(2,last/2).reverse()), a(seqN(2+(last/2-1)*1,last/2,fix<-1>)) );
|
||||
VERIFY_IS_APPROX( a(seqN(last/2,fix<4>).reverse()),a(seqN(last/2,fix<4>)).reverse() );
|
||||
VERIFY_IS_APPROX( A(seq(last-5,last-1,2).reverse(), seqN(last-3,3,fix<-2>).reverse()),
|
||||
A(seq(last-5,last-1,2), seqN(last-3,3,fix<-2>)).reverse() );
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
// check lastN
|
||||
VERIFY_IS_APPROX( a(lastN(3)), a.tail(3) );
|
||||
VERIFY( MATCH( a(lastN(3)), "7\n8\n9" ) );
|
||||
VERIFY_IS_APPROX( a(lastN(fix<3>())), a.tail<3>() );
|
||||
VERIFY( MATCH( a(lastN(3,2)), "5\n7\n9" ) );
|
||||
VERIFY( MATCH( a(lastN(3,fix<2>())), "5\n7\n9" ) );
|
||||
VERIFY( a(lastN(fix<3>())).SizeAtCompileTime == 3 );
|
||||
|
||||
VERIFY( (A(all, std::array<int,4>{{1,3,2,4}})).ColsAtCompileTime == 4);
|
||||
|
||||
VERIFY_IS_APPROX( (A(std::array<int,3>{{1,3,5}}, std::array<int,4>{{9,6,3,0}})), A(seqN(1,3,2), seqN(9,4,-3)) );
|
||||
|
||||
#if EIGEN_HAS_STATIC_ARRAY_TEMPLATE
|
||||
VERIFY_IS_APPROX( A({3, 1, 6, 5}, all), A(std::array<int,4>{{3, 1, 6, 5}}, all) );
|
||||
VERIFY_IS_APPROX( A(all,{3, 1, 6, 5}), A(all,std::array<int,4>{{3, 1, 6, 5}}) );
|
||||
VERIFY_IS_APPROX( A({1,3,5},{3, 1, 6, 5}), A(std::array<int,3>{{1,3,5}},std::array<int,4>{{3, 1, 6, 5}}) );
|
||||
|
||||
VERIFY_IS_EQUAL( A({1,3,5},{3, 1, 6, 5}).RowsAtCompileTime, 3 );
|
||||
VERIFY_IS_EQUAL( A({1,3,5},{3, 1, 6, 5}).ColsAtCompileTime, 4 );
|
||||
|
||||
VERIFY_IS_APPROX( a({3, 1, 6, 5}), a(std::array<int,4>{{3, 1, 6, 5}}) );
|
||||
VERIFY_IS_EQUAL( a({1,3,5}).SizeAtCompileTime, 3 );
|
||||
|
||||
VERIFY_IS_APPROX( b({3, 1, 6, 5}), b(std::array<int,4>{{3, 1, 6, 5}}) );
|
||||
VERIFY_IS_EQUAL( b({1,3,5}).SizeAtCompileTime, 3 );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// check mat(i,j) with weird types for i and j
|
||||
{
|
||||
VERIFY_IS_APPROX( A(B.RowsAtCompileTime-1, 1), A(3,1) );
|
||||
VERIFY_IS_APPROX( A(B.RowsAtCompileTime, 1), A(4,1) );
|
||||
VERIFY_IS_APPROX( A(B.RowsAtCompileTime-1, B.ColsAtCompileTime-1), A(3,3) );
|
||||
VERIFY_IS_APPROX( A(B.RowsAtCompileTime, B.ColsAtCompileTime), A(4,4) );
|
||||
const Index I_ = 3, J_ = 4;
|
||||
VERIFY_IS_APPROX( A(I_,J_), A(3,4) );
|
||||
}
|
||||
|
||||
// check extended block API
|
||||
{
|
||||
VERIFY( is_same_eq( A.block<3,4>(1,1), A.block(1,1,fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( A.block<3,4>(1,1,3,4), A.block(1,1,fix<3>(),fix<4>(4))) );
|
||||
VERIFY( is_same_eq( A.block<3,Dynamic>(1,1,3,4), A.block(1,1,fix<3>,4)) );
|
||||
VERIFY( is_same_eq( A.block<Dynamic,4>(1,1,3,4), A.block(1,1,fix<Dynamic>(3),fix<4>)) );
|
||||
VERIFY( is_same_eq( A.block(1,1,3,4), A.block(1,1,fix<Dynamic>(3),fix<Dynamic>(4))) );
|
||||
|
||||
VERIFY( is_same_eq( A.topLeftCorner<3,4>(), A.topLeftCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( A.bottomLeftCorner<3,4>(), A.bottomLeftCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( A.bottomRightCorner<3,4>(), A.bottomRightCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( A.topRightCorner<3,4>(), A.topRightCorner(fix<3>,fix<4>)) );
|
||||
|
||||
VERIFY( is_same_eq( A.leftCols<3>(), A.leftCols(fix<3>)) );
|
||||
VERIFY( is_same_eq( A.rightCols<3>(), A.rightCols(fix<3>)) );
|
||||
VERIFY( is_same_eq( A.middleCols<3>(1), A.middleCols(1,fix<3>)) );
|
||||
|
||||
VERIFY( is_same_eq( A.topRows<3>(), A.topRows(fix<3>)) );
|
||||
VERIFY( is_same_eq( A.bottomRows<3>(), A.bottomRows(fix<3>)) );
|
||||
VERIFY( is_same_eq( A.middleRows<3>(1), A.middleRows(1,fix<3>)) );
|
||||
|
||||
VERIFY( is_same_eq( a.segment<3>(1), a.segment(1,fix<3>)) );
|
||||
VERIFY( is_same_eq( a.head<3>(), a.head(fix<3>)) );
|
||||
VERIFY( is_same_eq( a.tail<3>(), a.tail(fix<3>)) );
|
||||
|
||||
const ArrayXXi& cA(A);
|
||||
VERIFY( is_same_eq( cA.block<Dynamic,4>(1,1,3,4), cA.block(1,1,fix<Dynamic>(3),fix<4>)) );
|
||||
|
||||
VERIFY( is_same_eq( cA.topLeftCorner<3,4>(), cA.topLeftCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( cA.bottomLeftCorner<3,4>(), cA.bottomLeftCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( cA.bottomRightCorner<3,4>(), cA.bottomRightCorner(fix<3>,fix<4>)) );
|
||||
VERIFY( is_same_eq( cA.topRightCorner<3,4>(), cA.topRightCorner(fix<3>,fix<4>)) );
|
||||
|
||||
VERIFY( is_same_eq( cA.leftCols<3>(), cA.leftCols(fix<3>)) );
|
||||
VERIFY( is_same_eq( cA.rightCols<3>(), cA.rightCols(fix<3>)) );
|
||||
VERIFY( is_same_eq( cA.middleCols<3>(1), cA.middleCols(1,fix<3>)) );
|
||||
|
||||
VERIFY( is_same_eq( cA.topRows<3>(), cA.topRows(fix<3>)) );
|
||||
VERIFY( is_same_eq( cA.bottomRows<3>(), cA.bottomRows(fix<3>)) );
|
||||
VERIFY( is_same_eq( cA.middleRows<3>(1), cA.middleRows(1,fix<3>)) );
|
||||
}
|
||||
|
||||
// Check compilation of enums as index type:
|
||||
a(XX) = 1;
|
||||
A(XX,YY) = 1;
|
||||
// Anonymous enums only work with C++11
|
||||
#if EIGEN_HAS_CXX11
|
||||
enum { X=0, Y=1 };
|
||||
a(X) = 1;
|
||||
A(X,Y) = 1;
|
||||
A(XX,Y) = 1;
|
||||
A(X,YY) = 1;
|
||||
#endif
|
||||
|
||||
// Check compilation of varying integer types as index types:
|
||||
Index i = n/2;
|
||||
short i_short(i);
|
||||
std::size_t i_sizet(i);
|
||||
VERIFY_IS_EQUAL( a(i), a.coeff(i_short) );
|
||||
VERIFY_IS_EQUAL( a(i), a.coeff(i_sizet) );
|
||||
|
||||
VERIFY_IS_EQUAL( A(i,i), A.coeff(i_short, i_short) );
|
||||
VERIFY_IS_EQUAL( A(i,i), A.coeff(i_short, i) );
|
||||
VERIFY_IS_EQUAL( A(i,i), A.coeff(i, i_short) );
|
||||
VERIFY_IS_EQUAL( A(i,i), A.coeff(i, i_sizet) );
|
||||
VERIFY_IS_EQUAL( A(i,i), A.coeff(i_sizet, i) );
|
||||
VERIFY_IS_EQUAL( A(i,i), A.coeff(i_sizet, i_short) );
|
||||
VERIFY_IS_EQUAL( A(i,i), A.coeff(5, i_sizet) );
|
||||
|
||||
// Regression test for Max{Rows,Cols}AtCompileTime
|
||||
{
|
||||
Matrix3i A3 = Matrix3i::Random();
|
||||
ArrayXi ind(5); ind << 1,1,1,1,1;
|
||||
VERIFY_IS_EQUAL( A3(ind,ind).eval(), MatrixXi::Constant(5,5,A3(1,1)) );
|
||||
}
|
||||
|
||||
// Regression for bug 1736
|
||||
{
|
||||
VERIFY_IS_APPROX(A(all, eii).col(0).eval(), A.col(eii(0)));
|
||||
A(all, eii).col(0) = A.col(eii(0));
|
||||
}
|
||||
|
||||
// bug 1815: IndexedView should allow linear access
|
||||
{
|
||||
VERIFY( MATCH( b(eii)(0), "3" ) );
|
||||
VERIFY( MATCH( a(eii)(0), "3" ) );
|
||||
VERIFY( MATCH( A(1,eii)(0), "103"));
|
||||
VERIFY( MATCH( A(eii,1)(0), "301"));
|
||||
VERIFY( MATCH( A(1,all)(1), "101"));
|
||||
VERIFY( MATCH( A(all,1)(1), "101"));
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
//Bug IndexView with a single static row should be RowMajor:
|
||||
{
|
||||
// A(1, seq(0,2,1)).cwiseAbs().colwise().replicate(2).eval();
|
||||
STATIC_CHECK(( (internal::evaluator<decltype( A(1,seq(0,2,1)) )>::Flags & RowMajorBit) == RowMajorBit ));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(indexed_view)
|
||||
{
|
||||
// for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( check_indexed_view() );
|
||||
CALL_SUBTEST_2( check_indexed_view() );
|
||||
CALL_SUBTEST_3( check_indexed_view() );
|
||||
// }
|
||||
|
||||
// static checks of some internals:
|
||||
STATIC_CHECK(( internal::is_valid_index_type<int>::value ));
|
||||
STATIC_CHECK(( internal::is_valid_index_type<unsigned int>::value ));
|
||||
STATIC_CHECK(( internal::is_valid_index_type<short>::value ));
|
||||
STATIC_CHECK(( internal::is_valid_index_type<std::ptrdiff_t>::value ));
|
||||
STATIC_CHECK(( internal::is_valid_index_type<std::size_t>::value ));
|
||||
STATIC_CHECK(( !internal::valid_indexed_view_overload<int,int>::value ));
|
||||
STATIC_CHECK(( !internal::valid_indexed_view_overload<int,std::ptrdiff_t>::value ));
|
||||
STATIC_CHECK(( !internal::valid_indexed_view_overload<std::ptrdiff_t,int>::value ));
|
||||
STATIC_CHECK(( !internal::valid_indexed_view_overload<std::size_t,int>::value ));
|
||||
}
|
||||
385
libs/eigen/test/initializer_list_construction.cpp
Normal file
385
libs/eigen/test/initializer_list_construction.cpp
Normal file
@@ -0,0 +1,385 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2019 David Tellenbach <david.tellenbach@tellnotes.org>
|
||||
//
|
||||
// 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 Scalar, bool is_integer = NumTraits<Scalar>::IsInteger>
|
||||
struct TestMethodDispatching {
|
||||
static void run() {}
|
||||
};
|
||||
|
||||
template<typename Scalar>
|
||||
struct TestMethodDispatching<Scalar, 1> {
|
||||
static void run()
|
||||
{
|
||||
{
|
||||
Matrix<Scalar, Dynamic, Dynamic> m {3, 4};
|
||||
Array<Scalar, Dynamic, Dynamic> a {3, 4};
|
||||
VERIFY(m.rows() == 3);
|
||||
VERIFY(m.cols() == 4);
|
||||
VERIFY(a.rows() == 3);
|
||||
VERIFY(a.cols() == 4);
|
||||
}
|
||||
{
|
||||
Matrix<Scalar, 1, 2> m {3, 4};
|
||||
Array<Scalar, 1, 2> a {3, 4};
|
||||
VERIFY(m(0) == 3);
|
||||
VERIFY(m(1) == 4);
|
||||
VERIFY(a(0) == 3);
|
||||
VERIFY(a(1) == 4);
|
||||
}
|
||||
{
|
||||
Matrix<Scalar, 2, 1> m {3, 4};
|
||||
Array<Scalar, 2, 1> a {3, 4};
|
||||
VERIFY(m(0) == 3);
|
||||
VERIFY(m(1) == 4);
|
||||
VERIFY(a(0) == 3);
|
||||
VERIFY(a(1) == 4);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Vec4, typename Vec5> void fixedsizeVariadicVectorConstruction2()
|
||||
{
|
||||
{
|
||||
Vec4 ref = Vec4::Random();
|
||||
Vec4 v{ ref[0], ref[1], ref[2], ref[3] };
|
||||
VERIFY_IS_APPROX(v, ref);
|
||||
VERIFY_IS_APPROX(v, (Vec4( ref[0], ref[1], ref[2], ref[3] )));
|
||||
VERIFY_IS_APPROX(v, (Vec4({ref[0], ref[1], ref[2], ref[3]})));
|
||||
|
||||
Vec4 v2 = { ref[0], ref[1], ref[2], ref[3] };
|
||||
VERIFY_IS_APPROX(v2, ref);
|
||||
}
|
||||
{
|
||||
Vec5 ref = Vec5::Random();
|
||||
Vec5 v{ ref[0], ref[1], ref[2], ref[3], ref[4] };
|
||||
VERIFY_IS_APPROX(v, ref);
|
||||
VERIFY_IS_APPROX(v, (Vec5( ref[0], ref[1], ref[2], ref[3], ref[4] )));
|
||||
VERIFY_IS_APPROX(v, (Vec5({ref[0], ref[1], ref[2], ref[3], ref[4]})));
|
||||
|
||||
Vec5 v2 = { ref[0], ref[1], ref[2], ref[3], ref[4] };
|
||||
VERIFY_IS_APPROX(v2, ref);
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK_MIXSCALAR_V5_APPROX(V, A0, A1, A2, A3, A4) { \
|
||||
VERIFY_IS_APPROX(V[0], Scalar(A0) ); \
|
||||
VERIFY_IS_APPROX(V[1], Scalar(A1) ); \
|
||||
VERIFY_IS_APPROX(V[2], Scalar(A2) ); \
|
||||
VERIFY_IS_APPROX(V[3], Scalar(A3) ); \
|
||||
VERIFY_IS_APPROX(V[4], Scalar(A4) ); \
|
||||
}
|
||||
|
||||
#define CHECK_MIXSCALAR_V5(VEC5, A0, A1, A2, A3, A4) { \
|
||||
typedef VEC5::Scalar Scalar; \
|
||||
VEC5 v = { A0 , A1 , A2 , A3 , A4 }; \
|
||||
CHECK_MIXSCALAR_V5_APPROX(v, A0 , A1 , A2 , A3 , A4); \
|
||||
}
|
||||
|
||||
template<int> void fixedsizeVariadicVectorConstruction3()
|
||||
{
|
||||
typedef Matrix<double,5,1> Vec5;
|
||||
typedef Array<float,5,1> Arr5;
|
||||
CHECK_MIXSCALAR_V5(Vec5, 1, 2., -3, 4.121, 5.53252);
|
||||
CHECK_MIXSCALAR_V5(Arr5, 1, 2., 3.12f, 4.121, 5.53252);
|
||||
}
|
||||
|
||||
template<typename Scalar> void fixedsizeVariadicVectorConstruction()
|
||||
{
|
||||
CALL_SUBTEST(( fixedsizeVariadicVectorConstruction2<Matrix<Scalar,4,1>, Matrix<Scalar,5,1> >() ));
|
||||
CALL_SUBTEST(( fixedsizeVariadicVectorConstruction2<Matrix<Scalar,1,4>, Matrix<Scalar,1,5> >() ));
|
||||
CALL_SUBTEST(( fixedsizeVariadicVectorConstruction2<Array<Scalar,4,1>, Array<Scalar,5,1> >() ));
|
||||
CALL_SUBTEST(( fixedsizeVariadicVectorConstruction2<Array<Scalar,1,4>, Array<Scalar,1,5> >() ));
|
||||
}
|
||||
|
||||
|
||||
template<typename Scalar> void initializerListVectorConstruction()
|
||||
{
|
||||
Scalar raw[4];
|
||||
for(int k = 0; k < 4; ++k) {
|
||||
raw[k] = internal::random<Scalar>();
|
||||
}
|
||||
{
|
||||
Matrix<Scalar, 4, 1> m { {raw[0]}, {raw[1]},{raw[2]},{raw[3]} };
|
||||
Array<Scalar, 4, 1> a { {raw[0]}, {raw[1]}, {raw[2]}, {raw[3]} };
|
||||
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, 1, 4> m { {raw[0], raw[1], raw[2], raw[3]} };
|
||||
Array<Scalar, 1, 4> a { {raw[0], raw[1], raw[2], raw[3]} };
|
||||
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, 1, 4>({{raw[0],raw[1],raw[2],raw[3]}})));
|
||||
VERIFY((a == (Array<Scalar, 1, 4>({{raw[0],raw[1],raw[2],raw[3]}}))).all());
|
||||
}
|
||||
{
|
||||
Matrix<Scalar, 4, Dynamic> m { {raw[0]}, {raw[1]}, {raw[2]}, {raw[3]} };
|
||||
Array<Scalar, 4, Dynamic> a { {raw[0]}, {raw[1]}, {raw[2]}, {raw[3]} };
|
||||
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, Dynamic>({ {raw[0]}, {raw[1]}, {raw[2]}, {raw[3]} })));
|
||||
VERIFY((a == (Array<Scalar, 4, Dynamic>({ {raw[0]}, {raw[1]}, {raw[2]}, {raw[3]} }))).all());
|
||||
}
|
||||
{
|
||||
Matrix<Scalar, Dynamic, 4> m {{raw[0],raw[1],raw[2],raw[3]}};
|
||||
Array<Scalar, Dynamic, 4> a {{raw[0],raw[1],raw[2],raw[3]}};
|
||||
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, Dynamic, 4>({{raw[0],raw[1],raw[2],raw[3]}})));
|
||||
VERIFY((a == (Array<Scalar, Dynamic, 4>({{raw[0],raw[1],raw[2],raw[3]}}))).all());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar> void initializerListMatrixConstruction()
|
||||
{
|
||||
const Index RowsAtCompileTime = 5;
|
||||
const Index ColsAtCompileTime = 4;
|
||||
const Index SizeAtCompileTime = RowsAtCompileTime * ColsAtCompileTime;
|
||||
|
||||
Scalar raw[SizeAtCompileTime];
|
||||
for (int i = 0; i < SizeAtCompileTime; ++i) {
|
||||
raw[i] = internal::random<Scalar>();
|
||||
}
|
||||
{
|
||||
Matrix<Scalar, Dynamic, Dynamic> m {};
|
||||
VERIFY(m.cols() == 0);
|
||||
VERIFY(m.rows() == 0);
|
||||
VERIFY_IS_EQUAL(m, (Matrix<Scalar, Dynamic, Dynamic>()));
|
||||
}
|
||||
{
|
||||
Matrix<Scalar, 5, 4> m {
|
||||
{raw[0], raw[1], raw[2], raw[3]},
|
||||
{raw[4], raw[5], raw[6], raw[7]},
|
||||
{raw[8], raw[9], raw[10], raw[11]},
|
||||
{raw[12], raw[13], raw[14], raw[15]},
|
||||
{raw[16], raw[17], raw[18], raw[19]}
|
||||
};
|
||||
|
||||
Matrix<Scalar, 5, 4> m2;
|
||||
m2 << raw[0], raw[1], raw[2], raw[3],
|
||||
raw[4], raw[5], raw[6], raw[7],
|
||||
raw[8], raw[9], raw[10], raw[11],
|
||||
raw[12], raw[13], raw[14], raw[15],
|
||||
raw[16], raw[17], raw[18], raw[19];
|
||||
|
||||
int k = 0;
|
||||
for(int i = 0; i < RowsAtCompileTime; ++i) {
|
||||
for (int j = 0; j < ColsAtCompileTime; ++j) {
|
||||
VERIFY(m(i, j) == raw[k]);
|
||||
++k;
|
||||
}
|
||||
}
|
||||
VERIFY_IS_EQUAL(m, m2);
|
||||
}
|
||||
{
|
||||
Matrix<Scalar, Dynamic, Dynamic> m{
|
||||
{raw[0], raw[1], raw[2], raw[3]},
|
||||
{raw[4], raw[5], raw[6], raw[7]},
|
||||
{raw[8], raw[9], raw[10], raw[11]},
|
||||
{raw[12], raw[13], raw[14], raw[15]},
|
||||
{raw[16], raw[17], raw[18], raw[19]}
|
||||
};
|
||||
|
||||
VERIFY(m.cols() == 4);
|
||||
VERIFY(m.rows() == 5);
|
||||
int k = 0;
|
||||
for(int i = 0; i < RowsAtCompileTime; ++i) {
|
||||
for (int j = 0; j < ColsAtCompileTime; ++j) {
|
||||
VERIFY(m(i, j) == raw[k]);
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
||||
Matrix<Scalar, Dynamic, Dynamic> m2(RowsAtCompileTime, ColsAtCompileTime);
|
||||
k = 0;
|
||||
for(int i = 0; i < RowsAtCompileTime; ++i) {
|
||||
for (int j = 0; j < ColsAtCompileTime; ++j) {
|
||||
m2(i, j) = raw[k];
|
||||
++k;
|
||||
}
|
||||
}
|
||||
VERIFY_IS_EQUAL(m, m2);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar> void initializerListArrayConstruction()
|
||||
{
|
||||
const Index RowsAtCompileTime = 5;
|
||||
const Index ColsAtCompileTime = 4;
|
||||
const Index SizeAtCompileTime = RowsAtCompileTime * ColsAtCompileTime;
|
||||
|
||||
Scalar raw[SizeAtCompileTime];
|
||||
for (int i = 0; i < SizeAtCompileTime; ++i) {
|
||||
raw[i] = internal::random<Scalar>();
|
||||
}
|
||||
{
|
||||
Array<Scalar, Dynamic, Dynamic> a {};
|
||||
VERIFY(a.cols() == 0);
|
||||
VERIFY(a.rows() == 0);
|
||||
}
|
||||
{
|
||||
Array<Scalar, 5, 4> m {
|
||||
{raw[0], raw[1], raw[2], raw[3]},
|
||||
{raw[4], raw[5], raw[6], raw[7]},
|
||||
{raw[8], raw[9], raw[10], raw[11]},
|
||||
{raw[12], raw[13], raw[14], raw[15]},
|
||||
{raw[16], raw[17], raw[18], raw[19]}
|
||||
};
|
||||
|
||||
Array<Scalar, 5, 4> m2;
|
||||
m2 << raw[0], raw[1], raw[2], raw[3],
|
||||
raw[4], raw[5], raw[6], raw[7],
|
||||
raw[8], raw[9], raw[10], raw[11],
|
||||
raw[12], raw[13], raw[14], raw[15],
|
||||
raw[16], raw[17], raw[18], raw[19];
|
||||
|
||||
int k = 0;
|
||||
for(int i = 0; i < RowsAtCompileTime; ++i) {
|
||||
for (int j = 0; j < ColsAtCompileTime; ++j) {
|
||||
VERIFY(m(i, j) == raw[k]);
|
||||
++k;
|
||||
}
|
||||
}
|
||||
VERIFY_IS_APPROX(m, m2);
|
||||
}
|
||||
{
|
||||
Array<Scalar, Dynamic, Dynamic> m {
|
||||
{raw[0], raw[1], raw[2], raw[3]},
|
||||
{raw[4], raw[5], raw[6], raw[7]},
|
||||
{raw[8], raw[9], raw[10], raw[11]},
|
||||
{raw[12], raw[13], raw[14], raw[15]},
|
||||
{raw[16], raw[17], raw[18], raw[19]}
|
||||
};
|
||||
|
||||
VERIFY(m.cols() == 4);
|
||||
VERIFY(m.rows() == 5);
|
||||
int k = 0;
|
||||
for(int i = 0; i < RowsAtCompileTime; ++i) {
|
||||
for (int j = 0; j < ColsAtCompileTime; ++j) {
|
||||
VERIFY(m(i, j) == raw[k]);
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
||||
Array<Scalar, Dynamic, Dynamic> m2(RowsAtCompileTime, ColsAtCompileTime);
|
||||
k = 0;
|
||||
for(int i = 0; i < RowsAtCompileTime; ++i) {
|
||||
for (int j = 0; j < ColsAtCompileTime; ++j) {
|
||||
m2(i, j) = raw[k];
|
||||
++k;
|
||||
}
|
||||
}
|
||||
VERIFY_IS_APPROX(m, m2);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar> void dynamicVectorConstruction()
|
||||
{
|
||||
const Index size = 4;
|
||||
Scalar raw[size];
|
||||
for (int i = 0; i < size; ++i) {
|
||||
raw[i] = internal::random<Scalar>();
|
||||
}
|
||||
|
||||
typedef Matrix<Scalar, Dynamic, 1> VectorX;
|
||||
|
||||
{
|
||||
VectorX v {{raw[0], raw[1], raw[2], raw[3]}};
|
||||
for (int i = 0; i < size; ++i) {
|
||||
VERIFY(v(i) == raw[i]);
|
||||
}
|
||||
VERIFY(v.rows() == size);
|
||||
VERIFY(v.cols() == 1);
|
||||
VERIFY_IS_EQUAL(v, (VectorX {{raw[0], raw[1], raw[2], raw[3]}}));
|
||||
}
|
||||
|
||||
{
|
||||
VERIFY_RAISES_ASSERT((VectorX {raw[0], raw[1], raw[2], raw[3]}));
|
||||
}
|
||||
{
|
||||
VERIFY_RAISES_ASSERT((VectorX {
|
||||
{raw[0], raw[1], raw[2], raw[3]},
|
||||
{raw[0], raw[1], raw[2], raw[3]},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(initializer_list_construction)
|
||||
{
|
||||
CALL_SUBTEST_1(initializerListVectorConstruction<unsigned char>());
|
||||
CALL_SUBTEST_1(initializerListVectorConstruction<float>());
|
||||
CALL_SUBTEST_1(initializerListVectorConstruction<double>());
|
||||
CALL_SUBTEST_1(initializerListVectorConstruction<int>());
|
||||
CALL_SUBTEST_1(initializerListVectorConstruction<long int>());
|
||||
CALL_SUBTEST_1(initializerListVectorConstruction<std::ptrdiff_t>());
|
||||
CALL_SUBTEST_1(initializerListVectorConstruction<std::complex<double>>());
|
||||
CALL_SUBTEST_1(initializerListVectorConstruction<std::complex<float>>());
|
||||
|
||||
CALL_SUBTEST_2(initializerListMatrixConstruction<unsigned char>());
|
||||
CALL_SUBTEST_2(initializerListMatrixConstruction<float>());
|
||||
CALL_SUBTEST_2(initializerListMatrixConstruction<double>());
|
||||
CALL_SUBTEST_2(initializerListMatrixConstruction<int>());
|
||||
CALL_SUBTEST_2(initializerListMatrixConstruction<long int>());
|
||||
CALL_SUBTEST_2(initializerListMatrixConstruction<std::ptrdiff_t>());
|
||||
CALL_SUBTEST_2(initializerListMatrixConstruction<std::complex<double>>());
|
||||
CALL_SUBTEST_2(initializerListMatrixConstruction<std::complex<float>>());
|
||||
|
||||
CALL_SUBTEST_3(initializerListArrayConstruction<unsigned char>());
|
||||
CALL_SUBTEST_3(initializerListArrayConstruction<float>());
|
||||
CALL_SUBTEST_3(initializerListArrayConstruction<double>());
|
||||
CALL_SUBTEST_3(initializerListArrayConstruction<int>());
|
||||
CALL_SUBTEST_3(initializerListArrayConstruction<long int>());
|
||||
CALL_SUBTEST_3(initializerListArrayConstruction<std::ptrdiff_t>());
|
||||
CALL_SUBTEST_3(initializerListArrayConstruction<std::complex<double>>());
|
||||
CALL_SUBTEST_3(initializerListArrayConstruction<std::complex<float>>());
|
||||
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction<unsigned char>());
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction<float>());
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction<double>());
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction<int>());
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction<long int>());
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction<std::ptrdiff_t>());
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction<std::complex<double>>());
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction<std::complex<float>>());
|
||||
CALL_SUBTEST_4(fixedsizeVariadicVectorConstruction3<0>());
|
||||
|
||||
CALL_SUBTEST_5(TestMethodDispatching<int>::run());
|
||||
CALL_SUBTEST_5(TestMethodDispatching<long int>::run());
|
||||
|
||||
CALL_SUBTEST_6(dynamicVectorConstruction<unsigned char>());
|
||||
CALL_SUBTEST_6(dynamicVectorConstruction<float>());
|
||||
CALL_SUBTEST_6(dynamicVectorConstruction<double>());
|
||||
CALL_SUBTEST_6(dynamicVectorConstruction<int>());
|
||||
CALL_SUBTEST_6(dynamicVectorConstruction<long int>());
|
||||
CALL_SUBTEST_6(dynamicVectorConstruction<std::ptrdiff_t>());
|
||||
CALL_SUBTEST_6(dynamicVectorConstruction<std::complex<double>>());
|
||||
CALL_SUBTEST_6(dynamicVectorConstruction<std::complex<float>>());
|
||||
}
|
||||
110
libs/eigen/test/inplace_decomposition.cpp
Normal file
110
libs/eigen/test/inplace_decomposition.cpp
Normal file
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DECLARE_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) ));
|
||||
}
|
||||
}
|
||||
173
libs/eigen/test/integer_types.cpp
Normal file
173
libs/eigen/test/integer_types.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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/.
|
||||
|
||||
#define EIGEN_NO_STATIC_ASSERT
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#undef VERIFY_IS_APPROX
|
||||
#define VERIFY_IS_APPROX(a, b) VERIFY((a)==(b));
|
||||
#undef VERIFY_IS_NOT_APPROX
|
||||
#define VERIFY_IS_NOT_APPROX(a, b) VERIFY((a)!=(b));
|
||||
|
||||
template<typename MatrixType> void signed_integer_type_tests(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
enum { is_signed = (Scalar(-1) > Scalar(0)) ? 0 : 1 };
|
||||
VERIFY(is_signed == 1);
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols);
|
||||
|
||||
do {
|
||||
m1 = MatrixType::Random(rows, cols);
|
||||
} while(m1 == mzero || m1 == m2);
|
||||
|
||||
// check linear structure
|
||||
|
||||
Scalar s1;
|
||||
do {
|
||||
s1 = internal::random<Scalar>();
|
||||
} while(s1 == 0);
|
||||
|
||||
VERIFY_IS_EQUAL(-(-m1), m1);
|
||||
VERIFY_IS_EQUAL(-m2+m1+m2, m1);
|
||||
VERIFY_IS_EQUAL((-m1+m2)*s1, -s1*m1+s1*m2);
|
||||
}
|
||||
|
||||
template<typename MatrixType> void integer_type_tests(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
VERIFY(NumTraits<Scalar>::IsInteger);
|
||||
enum { is_signed = (Scalar(-1) > Scalar(0)) ? 0 : 1 };
|
||||
VERIFY(int(NumTraits<Scalar>::IsSigned) == is_signed);
|
||||
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index 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(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols);
|
||||
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
|
||||
SquareMatrixType identity = SquareMatrixType::Identity(rows, rows),
|
||||
square = SquareMatrixType::Random(rows, rows);
|
||||
VectorType v1(rows),
|
||||
v2 = VectorType::Random(rows),
|
||||
vzero = VectorType::Zero(rows);
|
||||
|
||||
do {
|
||||
m1 = MatrixType::Random(rows, cols);
|
||||
} while(m1 == mzero || m1 == m2);
|
||||
|
||||
do {
|
||||
v1 = VectorType::Random(rows);
|
||||
} while(v1 == vzero || v1 == v2);
|
||||
|
||||
VERIFY_IS_APPROX( v1, v1);
|
||||
VERIFY_IS_NOT_APPROX( v1, 2*v1);
|
||||
VERIFY_IS_APPROX( vzero, v1-v1);
|
||||
VERIFY_IS_APPROX( m1, m1);
|
||||
VERIFY_IS_NOT_APPROX( m1, 2*m1);
|
||||
VERIFY_IS_APPROX( mzero, m1-m1);
|
||||
|
||||
VERIFY_IS_APPROX(m3 = m1,m1);
|
||||
MatrixType m4;
|
||||
VERIFY_IS_APPROX(m4 = m1,m1);
|
||||
|
||||
m3.real() = m1.real();
|
||||
VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), static_cast<const MatrixType&>(m1).real());
|
||||
VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), m1.real());
|
||||
|
||||
// check == / != operators
|
||||
VERIFY(m1==m1);
|
||||
VERIFY(m1!=m2);
|
||||
VERIFY(!(m1==m2));
|
||||
VERIFY(!(m1!=m1));
|
||||
m1 = m2;
|
||||
VERIFY(m1==m2);
|
||||
VERIFY(!(m1!=m2));
|
||||
|
||||
// check linear structure
|
||||
|
||||
Scalar s1;
|
||||
do {
|
||||
s1 = internal::random<Scalar>();
|
||||
} while(s1 == 0);
|
||||
|
||||
VERIFY_IS_EQUAL(m1+m1, 2*m1);
|
||||
VERIFY_IS_EQUAL(m1+m2-m1, m2);
|
||||
VERIFY_IS_EQUAL(m1*s1, s1*m1);
|
||||
VERIFY_IS_EQUAL((m1+m2)*s1, s1*m1+s1*m2);
|
||||
m3 = m2; m3 += m1;
|
||||
VERIFY_IS_EQUAL(m3, m1+m2);
|
||||
m3 = m2; m3 -= m1;
|
||||
VERIFY_IS_EQUAL(m3, m2-m1);
|
||||
m3 = m2; m3 *= s1;
|
||||
VERIFY_IS_EQUAL(m3, s1*m2);
|
||||
|
||||
// check matrix product.
|
||||
|
||||
VERIFY_IS_APPROX(identity * m1, m1);
|
||||
VERIFY_IS_APPROX(square * (m1 + m2), square * m1 + square * m2);
|
||||
VERIFY_IS_APPROX((m1 + m2).transpose() * square, m1.transpose() * square + m2.transpose() * square);
|
||||
VERIFY_IS_APPROX((m1 * m2.transpose()) * m1, m1 * (m2.transpose() * m1));
|
||||
}
|
||||
|
||||
template<int>
|
||||
void integer_types_extra()
|
||||
{
|
||||
VERIFY_IS_EQUAL(int(internal::scalar_div_cost<int>::value), 8);
|
||||
VERIFY_IS_EQUAL(int(internal::scalar_div_cost<unsigned int>::value), 8);
|
||||
if(sizeof(long)>sizeof(int)) {
|
||||
VERIFY(int(internal::scalar_div_cost<long>::value) > int(internal::scalar_div_cost<int>::value));
|
||||
VERIFY(int(internal::scalar_div_cost<unsigned long>::value) > int(internal::scalar_div_cost<int>::value));
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(integer_types)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( integer_type_tests(Matrix<unsigned int, 1, 1>()) );
|
||||
CALL_SUBTEST_1( integer_type_tests(Matrix<unsigned long, 3, 4>()) );
|
||||
|
||||
CALL_SUBTEST_2( integer_type_tests(Matrix<long, 2, 2>()) );
|
||||
CALL_SUBTEST_2( signed_integer_type_tests(Matrix<long, 2, 2>()) );
|
||||
|
||||
CALL_SUBTEST_3( integer_type_tests(Matrix<char, 2, Dynamic>(2, 10)) );
|
||||
CALL_SUBTEST_3( signed_integer_type_tests(Matrix<signed char, 2, Dynamic>(2, 10)) );
|
||||
|
||||
CALL_SUBTEST_4( integer_type_tests(Matrix<unsigned char, 3, 3>()) );
|
||||
CALL_SUBTEST_4( integer_type_tests(Matrix<unsigned char, Dynamic, Dynamic>(20, 20)) );
|
||||
|
||||
CALL_SUBTEST_5( integer_type_tests(Matrix<short, Dynamic, 4>(7, 4)) );
|
||||
CALL_SUBTEST_5( signed_integer_type_tests(Matrix<short, Dynamic, 4>(7, 4)) );
|
||||
|
||||
CALL_SUBTEST_6( integer_type_tests(Matrix<unsigned short, 4, 4>()) );
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
CALL_SUBTEST_7( integer_type_tests(Matrix<long long, 11, 13>()) );
|
||||
CALL_SUBTEST_7( signed_integer_type_tests(Matrix<long long, 11, 13>()) );
|
||||
|
||||
CALL_SUBTEST_8( integer_type_tests(Matrix<unsigned long long, Dynamic, 5>(1, 5)) );
|
||||
#endif
|
||||
}
|
||||
CALL_SUBTEST_9( integer_types_extra<0>() );
|
||||
}
|
||||
150
libs/eigen/test/inverse.cpp
Normal file
150
libs/eigen/test/inverse.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
// 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 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_for_fixed_size(const MatrixType&, typename internal::enable_if<MatrixType::SizeAtCompileTime==Dynamic>::type* = 0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
void inverse_for_fixed_size(const MatrixType& m1, typename internal::enable_if<MatrixType::SizeAtCompileTime!=Dynamic>::type* = 0)
|
||||
{
|
||||
using std::abs;
|
||||
|
||||
MatrixType m2, identity = MatrixType::Identity();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
//computeInverseAndDetWithCheck tests
|
||||
//First: an invertible matrix
|
||||
bool invertible;
|
||||
Scalar det;
|
||||
|
||||
m2.setZero();
|
||||
m1.computeInverseAndDetWithCheck(m2, det, invertible);
|
||||
VERIFY(invertible);
|
||||
VERIFY_IS_APPROX(identity, m1*m2);
|
||||
VERIFY_IS_APPROX(det, m1.determinant());
|
||||
|
||||
m2.setZero();
|
||||
m1.computeInverseWithCheck(m2, invertible);
|
||||
VERIFY(invertible);
|
||||
VERIFY_IS_APPROX(identity, m1*m2);
|
||||
|
||||
//Second: a rank one matrix (not invertible, except for 1x1 matrices)
|
||||
VectorType v3 = VectorType::Random();
|
||||
MatrixType m3 = v3*v3.transpose(), m4;
|
||||
m3.computeInverseAndDetWithCheck(m4, det, invertible);
|
||||
VERIFY( m1.rows()==1 ? invertible : !invertible );
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(abs(det-m3.determinant()), RealScalar(1));
|
||||
m3.computeInverseWithCheck(m4, invertible);
|
||||
VERIFY( m1.rows()==1 ? invertible : !invertible );
|
||||
|
||||
// check with submatrices
|
||||
{
|
||||
Matrix<Scalar, MatrixType::RowsAtCompileTime+1, MatrixType::RowsAtCompileTime+1, MatrixType::Options> m5;
|
||||
m5.setRandom();
|
||||
m5.topLeftCorner(m1.rows(),m1.rows()) = m1;
|
||||
m2 = m5.template topLeftCorner<MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime>().inverse();
|
||||
VERIFY_IS_APPROX( (m5.template topLeftCorner<MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime>()), m2.inverse() );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType> void inverse(const MatrixType& m)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
Inverse.h
|
||||
*/
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
MatrixType m1(rows, cols),
|
||||
m2(rows, cols),
|
||||
identity = MatrixType::Identity(rows, rows);
|
||||
createRandomPIMatrixOfRank(rows,rows,rows,m1);
|
||||
m2 = m1.inverse();
|
||||
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(MatrixType(m1.transpose().inverse()), MatrixType(m1.inverse().transpose()));
|
||||
|
||||
inverse_for_fixed_size(m1);
|
||||
|
||||
// check in-place inversion
|
||||
if(MatrixType::RowsAtCompileTime>=2 && MatrixType::RowsAtCompileTime<=4)
|
||||
{
|
||||
// in-place is forbidden
|
||||
VERIFY_RAISES_ASSERT(m1 = m1.inverse());
|
||||
}
|
||||
else
|
||||
{
|
||||
m2 = m1.inverse();
|
||||
m1 = m1.inverse();
|
||||
VERIFY_IS_APPROX(m1,m2);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
void inverse_zerosized()
|
||||
{
|
||||
Matrix<Scalar,Dynamic,Dynamic> A(0,0);
|
||||
{
|
||||
Matrix<Scalar,0,1> b, x;
|
||||
x = A.inverse() * b;
|
||||
}
|
||||
{
|
||||
Matrix<Scalar,Dynamic,Dynamic> b(0,1), x;
|
||||
x = A.inverse() * b;
|
||||
VERIFY_IS_EQUAL(x.rows(), 0);
|
||||
VERIFY_IS_EQUAL(x.cols(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(inverse)
|
||||
{
|
||||
int s = 0;
|
||||
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_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)
|
||||
CALL_SUBTEST_5( inverse_zerosized<float>() );
|
||||
CALL_SUBTEST_5( inverse(MatrixXf(0, 0)) );
|
||||
CALL_SUBTEST_5( inverse(MatrixXf(1, 1)) );
|
||||
|
||||
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>()) );
|
||||
|
||||
CALL_SUBTEST_8( inverse(Matrix4cd()) );
|
||||
}
|
||||
}
|
||||
71
libs/eigen/test/io.cpp
Normal file
71
libs/eigen/test/io.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2019 Joel Holdsworth <joel.holdsworth@vcatechnology.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 <sstream>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename Scalar>
|
||||
struct check_ostream_impl
|
||||
{
|
||||
static void run()
|
||||
{
|
||||
const Array<Scalar,1,1> array(123);
|
||||
std::ostringstream ss;
|
||||
ss << array;
|
||||
VERIFY(ss.str() == "123");
|
||||
|
||||
check_ostream_impl< std::complex<Scalar> >::run();
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct check_ostream_impl<bool>
|
||||
{
|
||||
static void run()
|
||||
{
|
||||
const Array<bool,1,2> array(1, 0);
|
||||
std::ostringstream ss;
|
||||
ss << array;
|
||||
VERIFY(ss.str() == "1 0");
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Scalar>
|
||||
struct check_ostream_impl< std::complex<Scalar> >
|
||||
{
|
||||
static void run()
|
||||
{
|
||||
const Array<std::complex<Scalar>,1,1> array(std::complex<Scalar>(12, 34));
|
||||
std::ostringstream ss;
|
||||
ss << array;
|
||||
VERIFY(ss.str() == "(12,34)");
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Scalar>
|
||||
static void check_ostream()
|
||||
{
|
||||
check_ostream_impl<Scalar>::run();
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(rand)
|
||||
{
|
||||
CALL_SUBTEST(check_ostream<bool>());
|
||||
CALL_SUBTEST(check_ostream<float>());
|
||||
CALL_SUBTEST(check_ostream<double>());
|
||||
CALL_SUBTEST(check_ostream<Eigen::numext::int8_t>());
|
||||
CALL_SUBTEST(check_ostream<Eigen::numext::uint8_t>());
|
||||
CALL_SUBTEST(check_ostream<Eigen::numext::int16_t>());
|
||||
CALL_SUBTEST(check_ostream<Eigen::numext::uint16_t>());
|
||||
CALL_SUBTEST(check_ostream<Eigen::numext::int32_t>());
|
||||
CALL_SUBTEST(check_ostream<Eigen::numext::uint32_t>());
|
||||
CALL_SUBTEST(check_ostream<Eigen::numext::int64_t>());
|
||||
CALL_SUBTEST(check_ostream<Eigen::numext::uint64_t>());
|
||||
}
|
||||
41
libs/eigen/test/is_same_dense.cpp
Normal file
41
libs/eigen/test/is_same_dense.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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;
|
||||
|
||||
EIGEN_DECLARE_TEST(is_same_dense)
|
||||
{
|
||||
typedef Matrix<double,Dynamic,Dynamic,ColMajor> ColMatrixXd;
|
||||
typedef Matrix<std::complex<double>,Dynamic,Dynamic,ColMajor> ColMatrixXcd;
|
||||
ColMatrixXd m1(10,10);
|
||||
ColMatrixXcd m2(10,10);
|
||||
Ref<ColMatrixXd> ref_m1(m1);
|
||||
Ref<ColMatrixXd,0, Stride<Dynamic,Dynamic> > ref_m2_real(m2.real());
|
||||
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));
|
||||
|
||||
|
||||
VERIFY(!is_same_dense(m1, ref_m2_real));
|
||||
VERIFY(!is_same_dense(m2, ref_m2_real));
|
||||
}
|
||||
80
libs/eigen/test/jacobi.cpp
Normal file
80
libs/eigen/test/jacobi.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// 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) 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/SVD>
|
||||
|
||||
template<typename MatrixType, typename JacobiScalar>
|
||||
void jacobi(const MatrixType& m = MatrixType())
|
||||
{
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime
|
||||
};
|
||||
|
||||
typedef Matrix<JacobiScalar, 2, 1> JacobiVector;
|
||||
|
||||
const MatrixType a(MatrixType::Random(rows, cols));
|
||||
|
||||
JacobiVector v = JacobiVector::Random().normalized();
|
||||
JacobiScalar c = v.x(), s = v.y();
|
||||
JacobiRotation<JacobiScalar> rot(c, s);
|
||||
|
||||
{
|
||||
Index p = internal::random<Index>(0, rows-1);
|
||||
Index q;
|
||||
do {
|
||||
q = internal::random<Index>(0, rows-1);
|
||||
} while (q == p);
|
||||
|
||||
MatrixType b = a;
|
||||
b.applyOnTheLeft(p, q, rot);
|
||||
VERIFY_IS_APPROX(b.row(p), c * a.row(p) + numext::conj(s) * a.row(q));
|
||||
VERIFY_IS_APPROX(b.row(q), -s * a.row(p) + numext::conj(c) * a.row(q));
|
||||
}
|
||||
|
||||
{
|
||||
Index p = internal::random<Index>(0, cols-1);
|
||||
Index q;
|
||||
do {
|
||||
q = internal::random<Index>(0, cols-1);
|
||||
} while (q == p);
|
||||
|
||||
MatrixType b = a;
|
||||
b.applyOnTheRight(p, q, rot);
|
||||
VERIFY_IS_APPROX(b.col(p), c * a.col(p) - s * a.col(q));
|
||||
VERIFY_IS_APPROX(b.col(q), numext::conj(s) * a.col(p) + numext::conj(c) * a.col(q));
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(jacobi)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1(( jacobi<Matrix3f, float>() ));
|
||||
CALL_SUBTEST_2(( jacobi<Matrix4d, double>() ));
|
||||
CALL_SUBTEST_3(( jacobi<Matrix4cf, float>() ));
|
||||
CALL_SUBTEST_3(( jacobi<Matrix4cf, std::complex<float> >() ));
|
||||
|
||||
int r = internal::random<int>(2, internal::random<int>(1,EIGEN_TEST_MAX_SIZE)/2),
|
||||
c = internal::random<int>(2, internal::random<int>(1,EIGEN_TEST_MAX_SIZE)/2);
|
||||
CALL_SUBTEST_4(( jacobi<MatrixXf, float>(MatrixXf(r,c)) ));
|
||||
CALL_SUBTEST_5(( jacobi<MatrixXcd, double>(MatrixXcd(r,c)) ));
|
||||
CALL_SUBTEST_5(( jacobi<MatrixXcd, std::complex<double> >(MatrixXcd(r,c)) ));
|
||||
// complex<float> is really important to test as it is the only way to cover conjugation issues in certain unaligned paths
|
||||
CALL_SUBTEST_6(( jacobi<MatrixXcf, float>(MatrixXcf(r,c)) ));
|
||||
CALL_SUBTEST_6(( jacobi<MatrixXcf, std::complex<float> >(MatrixXcf(r,c)) ));
|
||||
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(r);
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(c);
|
||||
}
|
||||
}
|
||||
147
libs/eigen/test/jacobisvd.cpp
Normal file
147
libs/eigen/test/jacobisvd.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
// 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/.
|
||||
|
||||
// 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>
|
||||
|
||||
#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)
|
||||
svd_fill_random(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)
|
||||
{
|
||||
svd_verify_assert<JacobiSVD<MatrixType> >(m);
|
||||
svd_verify_assert<JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner> >(m, true);
|
||||
svd_verify_assert<JacobiSVD<MatrixType, ColPivHouseholderQRPreconditioner> >(m);
|
||||
svd_verify_assert<JacobiSVD<MatrixType, HouseholderQRPreconditioner> >(m);
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
enum {
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime
|
||||
};
|
||||
|
||||
|
||||
MatrixType a = MatrixType::Zero(rows, cols);
|
||||
a.setZero();
|
||||
|
||||
if (ColsAtCompileTime == Dynamic)
|
||||
{
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
void jacobisvd_method()
|
||||
{
|
||||
enum { Size = MatrixType::RowsAtCompileTime };
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef Matrix<RealScalar, Size, 1> RealVecType;
|
||||
MatrixType m = MatrixType::Identity();
|
||||
VERIFY_IS_APPROX(m.jacobiSvd().singularValues(), RealVecType::Ones());
|
||||
VERIFY_RAISES_ASSERT(m.jacobiSvd().matrixU());
|
||||
VERIFY_RAISES_ASSERT(m.jacobiSvd().matrixV());
|
||||
VERIFY_IS_APPROX(m.jacobiSvd(ComputeFullU|ComputeFullV).solve(m), m);
|
||||
VERIFY_IS_APPROX(m.jacobiSvd(ComputeFullU|ComputeFullV).transpose().solve(m), m);
|
||||
VERIFY_IS_APPROX(m.jacobiSvd(ComputeFullU|ComputeFullV).adjoint().solve(m), m);
|
||||
}
|
||||
|
||||
namespace Foo {
|
||||
// older compiler require a default constructor for Bar
|
||||
// cf: https://stackoverflow.com/questions/7411515/
|
||||
class Bar {public: Bar() {}};
|
||||
bool operator<(const Bar&, const Bar&) { return true; }
|
||||
}
|
||||
// regression test for a very strange MSVC issue for which simply
|
||||
// including SVDBase.h messes up with std::max and custom scalar type
|
||||
void msvc_workaround()
|
||||
{
|
||||
const Foo::Bar a;
|
||||
const Foo::Bar b;
|
||||
std::max EIGEN_NOT_A_MACRO (a,b);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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++) {
|
||||
CALL_SUBTEST_3(( jacobisvd<Matrix3f>() ));
|
||||
CALL_SUBTEST_4(( jacobisvd<Matrix4d>() ));
|
||||
CALL_SUBTEST_5(( jacobisvd<Matrix<float,3,5> >() ));
|
||||
CALL_SUBTEST_6(( jacobisvd<Matrix<double,Dynamic,2> >(Matrix<double,Dynamic,2>(10,2)) ));
|
||||
|
||||
int r = internal::random<int>(1, 30),
|
||||
c = internal::random<int>(1, 30);
|
||||
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(r)
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(c)
|
||||
|
||||
CALL_SUBTEST_10(( jacobisvd<MatrixXd>(MatrixXd(r,c)) ));
|
||||
CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(r,c)) ));
|
||||
CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(r,c)) ));
|
||||
(void) r;
|
||||
(void) c;
|
||||
|
||||
// Test on inf/nan matrix
|
||||
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))) ));
|
||||
CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3))) ));
|
||||
|
||||
// test matrixbase method
|
||||
CALL_SUBTEST_1(( jacobisvd_method<Matrix2cd>() ));
|
||||
CALL_SUBTEST_3(( jacobisvd_method<Matrix3f>() ));
|
||||
|
||||
// Test problem size constructors
|
||||
CALL_SUBTEST_7( JacobiSVD<MatrixXf>(10,10) );
|
||||
|
||||
// Check that preallocation avoids subsequent mallocs
|
||||
CALL_SUBTEST_9( svd_preallocate<void>() );
|
||||
|
||||
CALL_SUBTEST_2( svd_underoverflow<void>() );
|
||||
|
||||
msvc_workaround();
|
||||
}
|
||||
32
libs/eigen/test/klu_support.cpp
Normal file
32
libs/eigen/test/klu_support.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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/.
|
||||
|
||||
#define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
|
||||
#include "sparse_solver.h"
|
||||
|
||||
#include <Eigen/KLUSupport>
|
||||
|
||||
template<typename T> void test_klu_support_T()
|
||||
{
|
||||
KLU<SparseMatrix<T, ColMajor> > klu_colmajor;
|
||||
KLU<SparseMatrix<T, RowMajor> > klu_rowmajor;
|
||||
|
||||
check_sparse_square_solving(klu_colmajor);
|
||||
check_sparse_square_solving(klu_rowmajor);
|
||||
|
||||
//check_sparse_square_determinant(umfpack_colmajor);
|
||||
//check_sparse_square_determinant(umfpack_rowmajor);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(klu_support)
|
||||
{
|
||||
CALL_SUBTEST_1(test_klu_support_T<double>());
|
||||
CALL_SUBTEST_2(test_klu_support_T<std::complex<double> >());
|
||||
}
|
||||
|
||||
147
libs/eigen/test/linearstructure.cpp
Normal file
147
libs/eigen/test/linearstructure.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// 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)
|
||||
{
|
||||
using std::abs;
|
||||
/* this test covers the following files:
|
||||
CwiseUnaryOp.h, CwiseBinaryOp.h, SelfCwiseBinaryOp.h
|
||||
*/
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index 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 = 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);
|
||||
|
||||
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>::IsInteger)
|
||||
{
|
||||
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>::IsInteger)
|
||||
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.cwiseProduct(m1.block(0,0,rows,cols)), m1.cwiseProduct(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);
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
template<int>
|
||||
void linearstructure_overflow()
|
||||
{
|
||||
// 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());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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()) );
|
||||
CALL_SUBTEST_3( linearStructure(Vector3d()) );
|
||||
CALL_SUBTEST_4( linearStructure(Matrix4d()) );
|
||||
CALL_SUBTEST_5( linearStructure(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
|
||||
CALL_SUBTEST_6( linearStructure(MatrixXf (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
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) );
|
||||
}
|
||||
CALL_SUBTEST_4( linearstructure_overflow<0>() );
|
||||
}
|
||||
37
libs/eigen/test/lscg.cpp
Normal file
37
libs/eigen/test/lscg.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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;
|
||||
LeastSquaresConjugateGradient<SparseMatrix<T,RowMajor> > lscg_rowmajor_diag;
|
||||
LeastSquaresConjugateGradient<SparseMatrix<T,RowMajor>, IdentityPreconditioner> lscg_rowmajor_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) );
|
||||
|
||||
CALL_SUBTEST( check_sparse_square_solving(lscg_rowmajor_diag) );
|
||||
CALL_SUBTEST( check_sparse_square_solving(lscg_rowmajor_I) );
|
||||
|
||||
CALL_SUBTEST( check_sparse_leastsquare_solving(lscg_rowmajor_diag) );
|
||||
CALL_SUBTEST( check_sparse_leastsquare_solving(lscg_rowmajor_I) );
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(lscg)
|
||||
{
|
||||
CALL_SUBTEST_1(test_lscg_T<double>());
|
||||
CALL_SUBTEST_2(test_lscg_T<std::complex<double> >());
|
||||
}
|
||||
252
libs/eigen/test/lu.cpp
Normal file
252
libs/eigen/test/lu.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-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 "solverbase.h"
|
||||
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()
|
||||
{
|
||||
STATIC_CHECK(( internal::is_same<typename FullPivLU<MatrixType>::StorageIndex,int>::value ));
|
||||
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
/* this test covers the following files:
|
||||
LU.h
|
||||
*/
|
||||
Index rows, cols, cols2;
|
||||
if(MatrixType::RowsAtCompileTime==Dynamic)
|
||||
{
|
||||
rows = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
rows = MatrixType::RowsAtCompileTime;
|
||||
}
|
||||
if(MatrixType::ColsAtCompileTime==Dynamic)
|
||||
{
|
||||
cols = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
|
||||
cols2 = internal::random<int>(2,EIGEN_TEST_MAX_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
cols2 = cols = MatrixType::ColsAtCompileTime;
|
||||
}
|
||||
|
||||
enum {
|
||||
RowsAtCompileTime = MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = MatrixType::ColsAtCompileTime
|
||||
};
|
||||
typedef typename internal::kernel_retval_base<FullPivLU<MatrixType> >::ReturnType KernelMatrixType;
|
||||
typedef typename internal::image_retval_base<FullPivLU<MatrixType> >::ReturnType ImageMatrixType;
|
||||
typedef Matrix<typename MatrixType::Scalar, ColsAtCompileTime, ColsAtCompileTime>
|
||||
CMatrixType;
|
||||
typedef Matrix<typename MatrixType::Scalar, RowsAtCompileTime, RowsAtCompileTime>
|
||||
RMatrixType;
|
||||
|
||||
Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
|
||||
|
||||
// The image of the zero matrix should consist of a single (zero) column vector
|
||||
VERIFY((MatrixType::Zero(rows,cols).fullPivLu().image(MatrixType::Zero(rows,cols)).cols() == 1));
|
||||
|
||||
// The kernel of the zero matrix is the entire space, and thus is an invertible matrix of dimensions cols.
|
||||
KernelMatrixType kernel = MatrixType::Zero(rows,cols).fullPivLu().kernel();
|
||||
VERIFY((kernel.fullPivLu().isInvertible()));
|
||||
|
||||
MatrixType m1(rows, cols), m3(rows, cols2);
|
||||
CMatrixType m2(cols, cols2);
|
||||
createRandomPIMatrixOfRank(rank, rows, cols, m1);
|
||||
|
||||
FullPivLU<MatrixType> lu;
|
||||
|
||||
// The special value 0.01 below works well in tests. Keep in mind that we're only computing the rank
|
||||
// of singular values are either 0 or 1.
|
||||
// So it's not clear at all that the epsilon should play any role there.
|
||||
lu.setThreshold(RealScalar(0.01));
|
||||
lu.compute(m1);
|
||||
|
||||
MatrixType u(rows,cols);
|
||||
u = lu.matrixLU().template triangularView<Upper>();
|
||||
RMatrixType l = RMatrixType::Identity(rows,rows);
|
||||
l.block(0,0,rows,(std::min)(rows,cols)).template triangularView<StrictlyLower>()
|
||||
= lu.matrixLU().block(0,0,rows,(std::min)(rows,cols));
|
||||
|
||||
VERIFY_IS_APPROX(lu.permutationP() * m1 * lu.permutationQ(), l*u);
|
||||
|
||||
KernelMatrixType m1kernel = lu.kernel();
|
||||
ImageMatrixType m1image = lu.image(m1);
|
||||
|
||||
VERIFY_IS_APPROX(m1, lu.reconstructedMatrix());
|
||||
VERIFY(rank == lu.rank());
|
||||
VERIFY(cols - lu.rank() == lu.dimensionOfKernel());
|
||||
VERIFY(!lu.isInjective());
|
||||
VERIFY(!lu.isInvertible());
|
||||
VERIFY(!lu.isSurjective());
|
||||
VERIFY_IS_MUCH_SMALLER_THAN((m1 * m1kernel), m1);
|
||||
VERIFY(m1image.fullPivLu().rank() == rank);
|
||||
VERIFY_IS_APPROX(m1 * m1.adjoint() * m1image, m1image);
|
||||
|
||||
check_solverbase<CMatrixType, MatrixType>(m1, lu, rows, cols, cols2);
|
||||
|
||||
m2 = CMatrixType::Random(cols,cols2);
|
||||
m3 = m1*m2;
|
||||
m2 = CMatrixType::Random(cols,cols2);
|
||||
// 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);
|
||||
}
|
||||
|
||||
template<typename MatrixType> void lu_invertible()
|
||||
{
|
||||
/* this test covers the following files:
|
||||
FullPivLU.h
|
||||
*/
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
Index size = MatrixType::RowsAtCompileTime;
|
||||
if( size==Dynamic)
|
||||
size = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
|
||||
MatrixType m1(size, size), m2(size, size), m3(size, size);
|
||||
FullPivLU<MatrixType> lu;
|
||||
lu.setThreshold(RealScalar(0.01));
|
||||
do {
|
||||
m1 = MatrixType::Random(size,size);
|
||||
lu.compute(m1);
|
||||
} while(!lu.isInvertible());
|
||||
|
||||
VERIFY_IS_APPROX(m1, lu.reconstructedMatrix());
|
||||
VERIFY(0 == lu.dimensionOfKernel());
|
||||
VERIFY(lu.kernel().cols() == 1); // the kernel() should consist of a single (zero) column vector
|
||||
VERIFY(size == lu.rank());
|
||||
VERIFY(lu.isInjective());
|
||||
VERIFY(lu.isSurjective());
|
||||
VERIFY(lu.isInvertible());
|
||||
VERIFY(lu.image(m1).fullPivLu().isInvertible());
|
||||
|
||||
check_solverbase<MatrixType, MatrixType>(m1, lu, size, size, size);
|
||||
|
||||
MatrixType m1_inverse = lu.inverse();
|
||||
m3 = MatrixType::Random(size,size);
|
||||
m2 = lu.solve(m3);
|
||||
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);
|
||||
|
||||
// Regression test for Bug 302
|
||||
MatrixType m4 = MatrixType::Random(size,size);
|
||||
VERIFY_IS_APPROX(lu.solve(m3*m4), lu.solve(m3)*m4);
|
||||
}
|
||||
|
||||
template<typename MatrixType> void lu_partial_piv(Index size = MatrixType::ColsAtCompileTime)
|
||||
{
|
||||
/* this test covers the following files:
|
||||
PartialPivLU.h
|
||||
*/
|
||||
typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
|
||||
|
||||
MatrixType m1(size, size), m2(size, size), m3(size, size);
|
||||
m1.setRandom();
|
||||
PartialPivLU<MatrixType> plu(m1);
|
||||
|
||||
STATIC_CHECK(( internal::is_same<typename PartialPivLU<MatrixType>::StorageIndex,int>::value ));
|
||||
|
||||
VERIFY_IS_APPROX(m1, plu.reconstructedMatrix());
|
||||
|
||||
check_solverbase<MatrixType, MatrixType>(m1, plu, size, size, size);
|
||||
|
||||
MatrixType m1_inverse = plu.inverse();
|
||||
m3 = MatrixType::Random(size,size);
|
||||
m2 = plu.solve(m3);
|
||||
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);
|
||||
}
|
||||
|
||||
template<typename MatrixType> void lu_verify_assert()
|
||||
{
|
||||
MatrixType tmp;
|
||||
|
||||
FullPivLU<MatrixType> lu;
|
||||
VERIFY_RAISES_ASSERT(lu.matrixLU())
|
||||
VERIFY_RAISES_ASSERT(lu.permutationP())
|
||||
VERIFY_RAISES_ASSERT(lu.permutationQ())
|
||||
VERIFY_RAISES_ASSERT(lu.kernel())
|
||||
VERIFY_RAISES_ASSERT(lu.image(tmp))
|
||||
VERIFY_RAISES_ASSERT(lu.solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(lu.transpose().solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(lu.adjoint().solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(lu.determinant())
|
||||
VERIFY_RAISES_ASSERT(lu.rank())
|
||||
VERIFY_RAISES_ASSERT(lu.dimensionOfKernel())
|
||||
VERIFY_RAISES_ASSERT(lu.isInjective())
|
||||
VERIFY_RAISES_ASSERT(lu.isSurjective())
|
||||
VERIFY_RAISES_ASSERT(lu.isInvertible())
|
||||
VERIFY_RAISES_ASSERT(lu.inverse())
|
||||
|
||||
PartialPivLU<MatrixType> plu;
|
||||
VERIFY_RAISES_ASSERT(plu.matrixLU())
|
||||
VERIFY_RAISES_ASSERT(plu.permutationP())
|
||||
VERIFY_RAISES_ASSERT(plu.solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(plu.transpose().solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(plu.adjoint().solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(plu.determinant())
|
||||
VERIFY_RAISES_ASSERT(plu.inverse())
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(lu)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( lu_non_invertible<Matrix3f>() );
|
||||
CALL_SUBTEST_1( lu_invertible<Matrix3f>() );
|
||||
CALL_SUBTEST_1( lu_verify_assert<Matrix3f>() );
|
||||
CALL_SUBTEST_1( lu_partial_piv<Matrix3f>() );
|
||||
|
||||
CALL_SUBTEST_2( (lu_non_invertible<Matrix<double, 4, 6> >()) );
|
||||
CALL_SUBTEST_2( (lu_verify_assert<Matrix<double, 4, 6> >()) );
|
||||
CALL_SUBTEST_2( lu_partial_piv<Matrix2d>() );
|
||||
CALL_SUBTEST_2( lu_partial_piv<Matrix4d>() );
|
||||
CALL_SUBTEST_2( (lu_partial_piv<Matrix<double,6,6> >()) );
|
||||
|
||||
CALL_SUBTEST_3( lu_non_invertible<MatrixXf>() );
|
||||
CALL_SUBTEST_3( lu_invertible<MatrixXf>() );
|
||||
CALL_SUBTEST_3( lu_verify_assert<MatrixXf>() );
|
||||
|
||||
CALL_SUBTEST_4( lu_non_invertible<MatrixXd>() );
|
||||
CALL_SUBTEST_4( lu_invertible<MatrixXd>() );
|
||||
CALL_SUBTEST_4( lu_partial_piv<MatrixXd>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) );
|
||||
CALL_SUBTEST_4( lu_verify_assert<MatrixXd>() );
|
||||
|
||||
CALL_SUBTEST_5( lu_non_invertible<MatrixXcf>() );
|
||||
CALL_SUBTEST_5( lu_invertible<MatrixXcf>() );
|
||||
CALL_SUBTEST_5( lu_verify_assert<MatrixXcf>() );
|
||||
|
||||
CALL_SUBTEST_6( lu_non_invertible<MatrixXcd>() );
|
||||
CALL_SUBTEST_6( lu_invertible<MatrixXcd>() );
|
||||
CALL_SUBTEST_6( lu_partial_piv<MatrixXcd>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) );
|
||||
CALL_SUBTEST_6( lu_verify_assert<MatrixXcd>() );
|
||||
|
||||
CALL_SUBTEST_7(( lu_non_invertible<Matrix<float,Dynamic,16> >() ));
|
||||
|
||||
// Test problem size constructors
|
||||
CALL_SUBTEST_9( PartialPivLU<MatrixXf>(10) );
|
||||
CALL_SUBTEST_9( FullPivLU<MatrixXf>(10, 20); );
|
||||
}
|
||||
}
|
||||
857
libs/eigen/test/main.h
Normal file
857
libs/eigen/test/main.h
Normal file
@@ -0,0 +1,857 @@
|
||||
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 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 <cstdlib>
|
||||
#include <cerrno>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
#include <functional>
|
||||
|
||||
// The following includes of STL headers have to be done _before_ the
|
||||
// definition of macros min() and max(). The reason is that many STL
|
||||
// implementations will not work properly as the min and max symbols collide
|
||||
// with the STL functions std:min() and std::max(). The STL headers may check
|
||||
// for the macro definition of min/max and issue a warning or undefine the
|
||||
// macros.
|
||||
//
|
||||
// Still, Windows defines min() and max() in windef.h as part of the regular
|
||||
// Windows system interfaces and many other Windows APIs depend on these
|
||||
// macros being available. To prevent the macro expansion of min/max and to
|
||||
// make Eigen compatible with the Windows environment all function calls of
|
||||
// std::min() and std::max() have to be written with parenthesis around the
|
||||
// function name.
|
||||
//
|
||||
// All STL headers used by Eigen should be included here. Because main.h is
|
||||
// included before any Eigen header and because the STL headers are guarded
|
||||
// against multiple inclusions, no STL header will see our own min/max macro
|
||||
// definitions.
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
// Disable ICC's std::complex operator specializations so we can use our own.
|
||||
#define _OVERRIDE_COMPLEX_SPECIALIZATION_ 1
|
||||
#include <complex>
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
|
||||
#include <random>
|
||||
#include <chrono>
|
||||
#ifdef EIGEN_USE_THREADS
|
||||
#include <future>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Same for cuda_fp16.h
|
||||
#if defined(__CUDACC__) && !defined(EIGEN_NO_CUDA)
|
||||
// Means the compiler is either nvcc or clang with CUDA enabled
|
||||
#define EIGEN_CUDACC __CUDACC__
|
||||
#endif
|
||||
#if defined(EIGEN_CUDACC)
|
||||
#include <cuda.h>
|
||||
#define EIGEN_CUDA_SDK_VER (CUDA_VERSION * 10)
|
||||
#else
|
||||
#define EIGEN_CUDA_SDK_VER 0
|
||||
#endif
|
||||
#if EIGEN_CUDA_SDK_VER >= 70500
|
||||
#include <cuda_fp16.h>
|
||||
#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
|
||||
// are defined here and any not-parenthesized min/max call will cause a
|
||||
// compiler error.
|
||||
#if !defined(__HIPCC__) && !defined(EIGEN_USE_SYCL)
|
||||
//
|
||||
// HIP header files include the following files
|
||||
// <thread>
|
||||
// <regex>
|
||||
// <unordered_map>
|
||||
// which seem to contain not-parenthesized calls to "max"/"min", triggering the following check and causing the compile to fail
|
||||
//
|
||||
// Including those header files before the following macro definition for "min" / "max", only partially resolves the issue
|
||||
// This is because other HIP header files also define "isnan" / "isinf" / "isfinite" functions, which are needed in other
|
||||
// headers.
|
||||
//
|
||||
// So instead choosing to simply disable this check for HIP
|
||||
//
|
||||
#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
|
||||
#endif
|
||||
|
||||
|
||||
// test possible conflicts
|
||||
struct real {};
|
||||
struct imag {};
|
||||
|
||||
#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
|
||||
// `I` may be defined by complex.h:
|
||||
#define I 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) 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
|
||||
|
||||
#include "split_test_helper.h"
|
||||
|
||||
#ifdef NDEBUG
|
||||
#undef NDEBUG
|
||||
#endif
|
||||
|
||||
// On windows CE, NDEBUG is automatically defined <assert.h> if NDEBUG is not defined.
|
||||
#ifndef DEBUG
|
||||
#define DEBUG
|
||||
#endif
|
||||
|
||||
// bounds integer values for AltiVec
|
||||
#if defined(__ALTIVEC__) || defined(__VSX__)
|
||||
#define EIGEN_MAKING_DOCS
|
||||
#endif
|
||||
|
||||
#define DEFAULT_REPEAT 10
|
||||
|
||||
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 = 1;
|
||||
static unsigned int g_seed = 0;
|
||||
static bool g_has_set_repeat = false, g_has_set_seed = false;
|
||||
|
||||
class EigenTest
|
||||
{
|
||||
public:
|
||||
EigenTest() : m_func(0) {}
|
||||
EigenTest(const char* a_name, void (*func)(void))
|
||||
: m_name(a_name), m_func(func)
|
||||
{
|
||||
get_registered_tests().push_back(this);
|
||||
}
|
||||
const std::string& name() const { return m_name; }
|
||||
void operator()() const { m_func(); }
|
||||
|
||||
static const std::vector<EigenTest*>& all() { return get_registered_tests(); }
|
||||
protected:
|
||||
static std::vector<EigenTest*>& get_registered_tests()
|
||||
{
|
||||
static std::vector<EigenTest*>* ms_registered_tests = new std::vector<EigenTest*>();
|
||||
return *ms_registered_tests;
|
||||
}
|
||||
std::string m_name;
|
||||
void (*m_func)(void);
|
||||
};
|
||||
|
||||
// Declare and register a test, e.g.:
|
||||
// EIGEN_DECLARE_TEST(mytest) { ... }
|
||||
// will create a function:
|
||||
// void test_mytest() { ... }
|
||||
// that will be automatically called.
|
||||
#define EIGEN_DECLARE_TEST(X) \
|
||||
void EIGEN_CAT(test_,X) (); \
|
||||
static EigenTest EIGEN_CAT(test_handler_,X) (EIGEN_MAKESTRING(X), & EIGEN_CAT(test_,X)); \
|
||||
void EIGEN_CAT(test_,X) ()
|
||||
}
|
||||
|
||||
#define TRACK std::cerr << __FILE__ << " " << __LINE__ << std::endl
|
||||
// #define TRACK while()
|
||||
|
||||
#define EIGEN_DEFAULT_IO_FORMAT IOFormat(4, 0, " ", "\n", "", "", "", "")
|
||||
|
||||
#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(__CUDA_ARCH__) && !defined(__HIP_DEVICE_COMPILE__) && !defined(__SYCL_DEVICE_ONLY__)
|
||||
#define EIGEN_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#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 triggered in a destructor.
|
||||
static bool no_more_assert = false;
|
||||
static bool report_on_cerr_on_assert_failure = true;
|
||||
|
||||
struct eigen_assert_exception
|
||||
{
|
||||
eigen_assert_exception(void) {}
|
||||
~eigen_assert_exception() { Eigen::no_more_assert = false; }
|
||||
};
|
||||
|
||||
struct eigen_static_assert_exception
|
||||
{
|
||||
eigen_static_assert_exception(void) {}
|
||||
~eigen_static_assert_exception() { Eigen::no_more_assert = false; }
|
||||
};
|
||||
}
|
||||
// If EIGEN_DEBUG_ASSERTS is defined and if no assertion is triggered while
|
||||
// one should have been, then the list of executed 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
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
static bool push_assert = false;
|
||||
}
|
||||
static std::vector<std::string> eigen_assert_list;
|
||||
}
|
||||
#define eigen_assert(a) \
|
||||
if( (!(a)) && (!no_more_assert) ) \
|
||||
{ \
|
||||
if(report_on_cerr_on_assert_failure) \
|
||||
std::cerr << #a << " " __FILE__ << "(" << __LINE__ << ")\n"; \
|
||||
Eigen::no_more_assert = true; \
|
||||
EIGEN_THROW_X(Eigen::eigen_assert_exception()); \
|
||||
} \
|
||||
else if (Eigen::internal::push_assert) \
|
||||
{ \
|
||||
eigen_assert_list.push_back(std::string(EIGEN_MAKESTRING(__FILE__) " (" EIGEN_MAKESTRING(__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::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"; \
|
||||
VERIFY(Eigen::should_raise_an_assert && # a); \
|
||||
} 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; \
|
||||
}
|
||||
#endif //EIGEN_EXCEPTIONS
|
||||
|
||||
#elif !defined(__CUDACC__) && !defined(__HIPCC__) && !defined(SYCL_DEVICE_ONLY) // 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) )\
|
||||
{ \
|
||||
Eigen::no_more_assert = true; \
|
||||
if(report_on_cerr_on_assert_failure) \
|
||||
eigen_plain_assert(a); \
|
||||
else \
|
||||
EIGEN_THROW_X(Eigen::eigen_assert_exception()); \
|
||||
}
|
||||
|
||||
#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); } \
|
||||
Eigen::report_on_cerr_on_assert_failure = true; \
|
||||
}
|
||||
#endif // EIGEN_EXCEPTIONS
|
||||
#endif // EIGEN_DEBUG_ASSERTS
|
||||
|
||||
#if defined(TEST_CHECK_STATIC_ASSERTIONS) && defined(EIGEN_EXCEPTIONS)
|
||||
#define EIGEN_STATIC_ASSERT(a,MSG) \
|
||||
if( (!Eigen::internal::copy_bool(a)) && (!no_more_assert) )\
|
||||
{ \
|
||||
Eigen::no_more_assert = true; \
|
||||
if(report_on_cerr_on_assert_failure) \
|
||||
eigen_plain_assert((a) && #MSG); \
|
||||
else \
|
||||
EIGEN_THROW_X(Eigen::eigen_static_assert_exception()); \
|
||||
}
|
||||
#define VERIFY_RAISES_STATIC_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_static_assert_exception&) { VERIFY(true); } \
|
||||
Eigen::report_on_cerr_on_assert_failure = true; \
|
||||
}
|
||||
#endif // TEST_CHECK_STATIC_ASSERTIONS
|
||||
|
||||
#ifndef VERIFY_RAISES_ASSERT
|
||||
#define VERIFY_RAISES_ASSERT(a) \
|
||||
std::cout << "Can't VERIFY_RAISES_ASSERT( " #a " ) with exceptions disabled\n";
|
||||
#endif
|
||||
#ifndef VERIFY_RAISES_STATIC_ASSERT
|
||||
#define VERIFY_RAISES_STATIC_ASSERT(a) \
|
||||
std::cout << "Can't VERIFY_RAISES_STATIC_ASSERT( " #a " ) with exceptions disabled\n";
|
||||
#endif
|
||||
|
||||
#if !defined(__CUDACC__) && !defined(__HIPCC__) && !defined(SYCL_DEVICE_ONLY)
|
||||
#define EIGEN_USE_CUSTOM_ASSERT
|
||||
#endif
|
||||
|
||||
#else // EIGEN_NO_ASSERTION_CHECKING
|
||||
|
||||
#define VERIFY_RAISES_ASSERT(a) {}
|
||||
#define VERIFY_RAISES_STATIC_ASSERT(a) {}
|
||||
|
||||
#endif // EIGEN_NO_ASSERTION_CHECKING
|
||||
|
||||
#define EIGEN_INTERNAL_DEBUGGING
|
||||
#include <Eigen/QR> // required for createRandomPIMatrixOfRank
|
||||
|
||||
inline void verify_impl(bool condition, const char *testname, const char *file, int line, const char *condition_as_string)
|
||||
{
|
||||
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";
|
||||
const int test_stack_size = static_cast<int>(Eigen::g_test_stack.size());
|
||||
for(int i=test_stack_size-1; i>=0; --i)
|
||||
std::cerr << " - " << Eigen::g_test_stack[i] << "\n";
|
||||
std::cerr << "\n";
|
||||
if(Eigen::g_test_level==0)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#define VERIFY(a) ::verify_impl(a, g_test_stack.back().c_str(), __FILE__, __LINE__, EIGEN_MAKESTRING(a))
|
||||
|
||||
#define VERIFY_GE(a, b) ::verify_impl(a >= b, g_test_stack.back().c_str(), __FILE__, __LINE__, EIGEN_MAKESTRING(a >= b))
|
||||
#define VERIFY_LE(a, b) ::verify_impl(a <= b, g_test_stack.back().c_str(), __FILE__, __LINE__, EIGEN_MAKESTRING(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))
|
||||
#define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) VERIFY(test_isApproxOrLessThan(a, b))
|
||||
#define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) VERIFY(!test_isApproxOrLessThan(a, b))
|
||||
|
||||
#define VERIFY_IS_UNITARY(a) VERIFY(test_isUnitary(a))
|
||||
|
||||
#define STATIC_CHECK(COND) EIGEN_STATIC_ASSERT( (COND) , EIGEN_INTERNAL_ERROR_PLEASE_FILE_A_BUG_REPORT )
|
||||
|
||||
#define CALL_SUBTEST(FUNC) do { \
|
||||
g_test_stack.push_back(EIGEN_MAKESTRING(FUNC)); \
|
||||
FUNC; \
|
||||
g_test_stack.pop_back(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
template<typename T1,typename T2>
|
||||
typename internal::enable_if<internal::is_same<T1,T2>::value,bool>::type
|
||||
is_same_type(const T1&, const T2&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
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<std::complex<long double> >() { return test_precision<long double>(); }
|
||||
|
||||
#define EIGEN_TEST_SCALAR_TEST_OVERLOAD(TYPE) \
|
||||
inline bool test_isApprox(TYPE a, TYPE b) \
|
||||
{ return internal::isApprox(a, b, test_precision<TYPE>()); } \
|
||||
inline bool test_isMuchSmallerThan(TYPE a, TYPE b) \
|
||||
{ return internal::isMuchSmallerThan(a, b, test_precision<TYPE>()); } \
|
||||
inline bool test_isApproxOrLessThan(TYPE a, TYPE b) \
|
||||
{ return internal::isApproxOrLessThan(a, b, test_precision<TYPE>()); }
|
||||
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(short)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(unsigned short)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(int)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(unsigned int)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(long)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(unsigned long)
|
||||
#if EIGEN_HAS_CXX11
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(long long)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(unsigned long long)
|
||||
#endif
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(float)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(double)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(half)
|
||||
EIGEN_TEST_SCALAR_TEST_OVERLOAD(bfloat16)
|
||||
|
||||
#undef EIGEN_TEST_SCALAR_TEST_OVERLOAD
|
||||
|
||||
#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)
|
||||
{ return internal::isMuchSmallerThan(a, b, test_precision<std::complex<float> >()); }
|
||||
|
||||
inline bool test_isApprox(const std::complex<double>& a, const std::complex<double>& b)
|
||||
{ return internal::isApprox(a, b, test_precision<std::complex<double> >()); }
|
||||
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>());
|
||||
if (!ret) std::cerr
|
||||
<< std::endl << " actual = " << a
|
||||
<< std::endl << " expected = " << b << std::endl << std::endl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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))/(numext::mini)(RealScalar(numext::abs2(a)),RealScalar(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, 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
|
||||
// Therefore, if for some reason a and b are very small compared to ref,
|
||||
// we won't issue a false negative.
|
||||
// This test could be: abs(a-b) <= eps * ref
|
||||
// However, it seems that simply comparing a+ref and b+ref is more sensitive to true error.
|
||||
template<typename Scalar,typename ScalarRef>
|
||||
inline bool test_isApproxWithRef(const Scalar& a, const Scalar& b, const ScalarRef& ref)
|
||||
{
|
||||
return test_isApprox(a+ref, b+ref);
|
||||
}
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
inline bool test_isMuchSmallerThan(const MatrixBase<Derived1>& m1,
|
||||
const MatrixBase<Derived2>& m2)
|
||||
{
|
||||
return m1.isMuchSmallerThan(m2, test_precision<typename internal::traits<Derived1>::Scalar>());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline bool test_isMuchSmallerThan(const MatrixBase<Derived>& m,
|
||||
const typename NumTraits<typename internal::traits<Derived>::Scalar>::Real& s)
|
||||
{
|
||||
return m.isMuchSmallerThan(s, test_precision<typename internal::traits<Derived>::Scalar>());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline bool test_isUnitary(const MatrixBase<Derived>& m)
|
||||
{
|
||||
return m.isUnitary(test_precision<typename internal::traits<Derived>::Scalar>());
|
||||
}
|
||||
|
||||
// Forward declaration to avoid ICC warning
|
||||
template<typename T, typename U>
|
||||
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 expect_equal)
|
||||
{
|
||||
if ((actual==expected) == expect_equal)
|
||||
return true;
|
||||
// false:
|
||||
std::cerr
|
||||
<< "\n actual = " << actual
|
||||
<< "\n expected " << (expect_equal ? "= " : "!=") << expected << "\n\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Creates a random Partial Isometry matrix of given rank.
|
||||
*
|
||||
* A partial isometry is a matrix all of whose singular values are either 0 or 1.
|
||||
* This is very useful to test rank-revealing algorithms.
|
||||
*/
|
||||
// Forward declaration to avoid ICC warning
|
||||
template<typename MatrixType>
|
||||
void createRandomPIMatrixOfRank(Index desired_rank, Index rows, Index cols, MatrixType& m);
|
||||
template<typename MatrixType>
|
||||
void createRandomPIMatrixOfRank(Index desired_rank, Index rows, Index cols, MatrixType& m)
|
||||
{
|
||||
typedef typename internal::traits<MatrixType>::Scalar Scalar;
|
||||
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
|
||||
|
||||
typedef Matrix<Scalar, Dynamic, 1> VectorType;
|
||||
typedef Matrix<Scalar, Rows, Rows> MatrixAType;
|
||||
typedef Matrix<Scalar, Cols, Cols> MatrixBType;
|
||||
|
||||
if(desired_rank == 0)
|
||||
{
|
||||
m.setZero(rows,cols);
|
||||
return;
|
||||
}
|
||||
|
||||
if(desired_rank == 1)
|
||||
{
|
||||
// here we normalize the vectors to get a partial isometry
|
||||
m = VectorType::Random(rows).normalized() * VectorType::Random(cols).normalized().transpose();
|
||||
return;
|
||||
}
|
||||
|
||||
MatrixAType a = MatrixAType::Random(rows,rows);
|
||||
MatrixType d = MatrixType::Identity(rows,cols);
|
||||
MatrixBType b = MatrixBType::Random(cols,cols);
|
||||
|
||||
// set the diagonal such that only desired_rank non-zero entries reamain
|
||||
const Index diag_size = (std::min)(d.rows(),d.cols());
|
||||
if(diag_size != desired_rank)
|
||||
d.diagonal().segment(desired_rank, diag_size-desired_rank) = VectorType::Zero(diag_size-desired_rank);
|
||||
|
||||
HouseholderQR<MatrixAType> qra(a);
|
||||
HouseholderQR<MatrixBType> qrb(b);
|
||||
m = qra.householderQ() * d * qrb.householderQ();
|
||||
}
|
||||
|
||||
// Forward declaration to avoid ICC warning
|
||||
template<typename PermutationVectorType>
|
||||
void randomPermutationVector(PermutationVectorType& v, Index size);
|
||||
template<typename PermutationVectorType>
|
||||
void randomPermutationVector(PermutationVectorType& v, Index size)
|
||||
{
|
||||
typedef typename PermutationVectorType::Scalar Scalar;
|
||||
v.resize(size);
|
||||
for(Index i = 0; i < size; ++i) v(i) = Scalar(i);
|
||||
if(size == 1) return;
|
||||
for(Index n = 0; n < 3 * size; ++n)
|
||||
{
|
||||
Index i = internal::random<Index>(0, size-1);
|
||||
Index j;
|
||||
do j = internal::random<Index>(0, size-1); while(j==i);
|
||||
std::swap(v(i), v(j));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> bool isNotNaN(const T& x)
|
||||
{
|
||||
return x==x;
|
||||
}
|
||||
|
||||
template<typename T> bool isPlusInf(const T& x)
|
||||
{
|
||||
return x > NumTraits<T>::highest();
|
||||
}
|
||||
|
||||
template<typename T> bool isMinusInf(const T& x)
|
||||
{
|
||||
return x < NumTraits<T>::lowest();
|
||||
}
|
||||
|
||||
} // 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 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<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>"; }
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
inline void set_repeat_from_string(const char *str)
|
||||
{
|
||||
errno = 0;
|
||||
g_repeat = int(strtoul(str, 0, 10));
|
||||
if(errno || g_repeat <= 0)
|
||||
{
|
||||
std::cout << "Invalid repeat value " << str << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_has_set_repeat = true;
|
||||
}
|
||||
|
||||
inline void set_seed_from_string(const char *str)
|
||||
{
|
||||
errno = 0;
|
||||
g_seed = int(strtoul(str, 0, 10));
|
||||
if(errno || g_seed == 0)
|
||||
{
|
||||
std::cout << "Invalid seed value " << str << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_has_set_seed = true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
g_has_set_repeat = false;
|
||||
g_has_set_seed = false;
|
||||
bool need_help = false;
|
||||
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
if(argv[i][0] == 'r')
|
||||
{
|
||||
if(g_has_set_repeat)
|
||||
{
|
||||
std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
set_repeat_from_string(argv[i]+1);
|
||||
}
|
||||
else if(argv[i][0] == 's')
|
||||
{
|
||||
if(g_has_set_seed)
|
||||
{
|
||||
std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
set_seed_from_string(argv[i]+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;
|
||||
std::cout << std::endl;
|
||||
std::cout << "If defined, the environment variables EIGEN_REPEAT and EIGEN_SEED" << std::endl;
|
||||
std::cout << "will be used as default values for these parameters." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *env_EIGEN_REPEAT = getenv("EIGEN_REPEAT");
|
||||
if(!g_has_set_repeat && env_EIGEN_REPEAT)
|
||||
set_repeat_from_string(env_EIGEN_REPEAT);
|
||||
char *env_EIGEN_SEED = getenv("EIGEN_SEED");
|
||||
if(!g_has_set_seed && env_EIGEN_SEED)
|
||||
set_seed_from_string(env_EIGEN_SEED);
|
||||
|
||||
if(!g_has_set_seed) g_seed = (unsigned int) time(NULL);
|
||||
if(!g_has_set_repeat) g_repeat = DEFAULT_REPEAT;
|
||||
|
||||
std::cout << "Initializing random number generator with seed " << g_seed << std::endl;
|
||||
std::stringstream ss;
|
||||
ss << "Seed: " << g_seed;
|
||||
g_test_stack.push_back(ss.str());
|
||||
srand(g_seed);
|
||||
std::cout << "Repeating each test " << g_repeat << " times" << std::endl;
|
||||
|
||||
VERIFY(EigenTest::all().size()>0);
|
||||
|
||||
for(std::size_t i=0; i<EigenTest::all().size(); ++i)
|
||||
{
|
||||
const EigenTest& current_test = *EigenTest::all()[i];
|
||||
Eigen::g_test_stack.push_back(current_test.name());
|
||||
current_test();
|
||||
Eigen::g_test_stack.pop_back();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// These warning are disabled here such that they are still ON when parsing Eigen's header files.
|
||||
#if defined __INTEL_COMPILER
|
||||
// remark #383: value copied to temporary, reference to temporary used
|
||||
// -> this warning is raised even for legal usage as: g_test_stack.push_back("foo"); where g_test_stack is a std::vector<std::string>
|
||||
// remark #1418: external function definition with no prior declaration
|
||||
// -> this warning is raised for all our test functions. Declaring them static would fix the issue.
|
||||
// warning #279: controlling expression is constant
|
||||
// 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
|
||||
207
libs/eigen/test/mapped_matrix.cpp
Normal file
207
libs/eigen/test/mapped_matrix.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2006-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/.
|
||||
|
||||
#ifndef EIGEN_NO_STATIC_ASSERT
|
||||
#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define EIGEN_TESTMAP_MAX_SIZE 256
|
||||
|
||||
template<typename VectorType> void map_class_vector(const VectorType& m)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
|
||||
Index size = m.size();
|
||||
|
||||
Scalar* array1 = internal::aligned_new<Scalar>(size);
|
||||
Scalar* array2 = internal::aligned_new<Scalar>(size);
|
||||
Scalar* array3 = new Scalar[size+1];
|
||||
Scalar* array3unaligned = (internal::UIntPtr(array3)%EIGEN_MAX_ALIGN_BYTES) == 0 ? array3+1 : array3;
|
||||
Scalar array4[EIGEN_TESTMAP_MAX_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);
|
||||
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 && size>=AlignedMax)
|
||||
VERIFY_RAISES_ASSERT((Map<VectorType,AlignedMax>(array3unaligned, size)))
|
||||
#endif
|
||||
|
||||
internal::aligned_delete(array1, size);
|
||||
internal::aligned_delete(array2, size);
|
||||
delete[] array3;
|
||||
}
|
||||
|
||||
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>();
|
||||
|
||||
// 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];
|
||||
Index sizep1 = size + 1; // <- without this temporary MSVC 2103 generates bad code
|
||||
for(Index i = 0; i < sizep1; i++) array3[i] = Scalar(1);
|
||||
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);
|
||||
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);
|
||||
delete[] array3;
|
||||
}
|
||||
|
||||
template<typename VectorType> void map_static_methods(const VectorType& m)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
|
||||
Index size = m.size();
|
||||
|
||||
Scalar* array1 = internal::aligned_new<Scalar>(size);
|
||||
Scalar* array2 = internal::aligned_new<Scalar>(size);
|
||||
Scalar* array3 = new Scalar[size+1];
|
||||
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);
|
||||
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_EQUAL(ma1, ma2);
|
||||
VERIFY_IS_EQUAL(ma1, ma3);
|
||||
|
||||
internal::aligned_delete(array1, size);
|
||||
internal::aligned_delete(array2, size);
|
||||
delete[] array3;
|
||||
}
|
||||
|
||||
template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
|
||||
{
|
||||
// there's a lot that we can't test here while still having this test compile!
|
||||
// the only possible approach would be to run a script trying to compile stuff and checking that it fails.
|
||||
// CMake can help with that.
|
||||
|
||||
// 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, AlignedMax> >::Flags & LvalueBit) );
|
||||
VERIFY( !(Map<ConstPlainObjectType>::Flags & LvalueBit) );
|
||||
VERIFY( !(Map<ConstPlainObjectType, AlignedMax>::Flags & LvalueBit) );
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
void map_not_aligned_on_scalar()
|
||||
{
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType;
|
||||
Index size = 11;
|
||||
Scalar* array1 = internal::aligned_new<Scalar>((size+1)*(size+1)+1);
|
||||
Scalar* array2 = reinterpret_cast<Scalar*>(sizeof(Scalar)/2+std::size_t(array1));
|
||||
Map<MatrixType,0,OuterStride<> > map2(array2, size, size, OuterStride<>(size+1));
|
||||
MatrixType m2 = MatrixType::Random(size,size);
|
||||
map2 = m2;
|
||||
VERIFY_IS_EQUAL(m2, map2);
|
||||
|
||||
typedef Matrix<Scalar,Dynamic,1> VectorType;
|
||||
Map<VectorType> map3(array2, size);
|
||||
MatrixType v3 = VectorType::Random(size);
|
||||
map3 = v3;
|
||||
VERIFY_IS_EQUAL(v3, map3);
|
||||
|
||||
internal::aligned_delete(array1, (size+1)*(size+1)+1);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(mapped_matrix)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
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)) );
|
||||
CALL_SUBTEST_5( map_class_vector(VectorXi(12)) );
|
||||
CALL_SUBTEST_5( check_const_correctness(VectorXi(12)) );
|
||||
|
||||
CALL_SUBTEST_1( map_class_matrix(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( map_class_matrix(Matrix4d()) );
|
||||
CALL_SUBTEST_11( map_class_matrix(Matrix<float,3,5>()) );
|
||||
CALL_SUBTEST_4( map_class_matrix(MatrixXcf(internal::random<int>(1,10),internal::random<int>(1,10))) );
|
||||
CALL_SUBTEST_5( map_class_matrix(MatrixXi(internal::random<int>(1,10),internal::random<int>(1,10))) );
|
||||
|
||||
CALL_SUBTEST_6( map_static_methods(Matrix<double, 1, 1>()) );
|
||||
CALL_SUBTEST_7( map_static_methods(Vector3f()) );
|
||||
CALL_SUBTEST_8( map_static_methods(RowVector3d()) );
|
||||
CALL_SUBTEST_9( map_static_methods(VectorXcd(8)) );
|
||||
CALL_SUBTEST_10( map_static_methods(VectorXf(12)) );
|
||||
CALL_SUBTEST_11( map_not_aligned_on_scalar<double>() );
|
||||
}
|
||||
}
|
||||
177
libs/eigen/test/mapstaticmethods.cpp
Normal file
177
libs/eigen/test/mapstaticmethods.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2011 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"
|
||||
|
||||
// GCC<=4.8 has spurious shadow warnings, because `ptr` re-appears inside template instantiations
|
||||
// workaround: put these in an anonymous namespace
|
||||
namespace {
|
||||
float *ptr;
|
||||
const float *const_ptr;
|
||||
}
|
||||
|
||||
template<typename PlainObjectType,
|
||||
bool IsDynamicSize = PlainObjectType::SizeAtCompileTime == Dynamic,
|
||||
bool IsVector = PlainObjectType::IsVectorAtCompileTime
|
||||
>
|
||||
struct mapstaticmethods_impl {};
|
||||
|
||||
template<typename PlainObjectType, bool IsVector>
|
||||
struct mapstaticmethods_impl<PlainObjectType, false, IsVector>
|
||||
{
|
||||
static void run(const PlainObjectType& m)
|
||||
{
|
||||
mapstaticmethods_impl<PlainObjectType, true, IsVector>::run(m);
|
||||
|
||||
int i = internal::random<int>(2,5), j = internal::random<int>(2,5);
|
||||
|
||||
PlainObjectType::Map(ptr).setZero();
|
||||
PlainObjectType::MapAligned(ptr).setZero();
|
||||
PlainObjectType::Map(const_ptr).sum();
|
||||
PlainObjectType::MapAligned(const_ptr).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, InnerStride<>(i)).setZero();
|
||||
PlainObjectType::MapAligned(ptr, InnerStride<>(i)).setZero();
|
||||
PlainObjectType::Map(const_ptr, InnerStride<>(i)).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, InnerStride<>(i)).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, InnerStride<2>()).setZero();
|
||||
PlainObjectType::MapAligned(ptr, InnerStride<3>()).setZero();
|
||||
PlainObjectType::Map(const_ptr, InnerStride<4>()).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, InnerStride<5>()).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, OuterStride<>(i)).setZero();
|
||||
PlainObjectType::MapAligned(ptr, OuterStride<>(i)).setZero();
|
||||
PlainObjectType::Map(const_ptr, OuterStride<>(i)).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, OuterStride<>(i)).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, OuterStride<2>()).setZero();
|
||||
PlainObjectType::MapAligned(ptr, OuterStride<3>()).setZero();
|
||||
PlainObjectType::Map(const_ptr, OuterStride<4>()).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, OuterStride<5>()).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, Stride<Dynamic, Dynamic>(i,j)).setZero();
|
||||
PlainObjectType::MapAligned(ptr, Stride<2,Dynamic>(2,i)).setZero();
|
||||
PlainObjectType::Map(const_ptr, Stride<Dynamic,3>(i,3)).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, Stride<Dynamic, Dynamic>(i,j)).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, Stride<2,3>()).setZero();
|
||||
PlainObjectType::MapAligned(ptr, Stride<3,4>()).setZero();
|
||||
PlainObjectType::Map(const_ptr, Stride<2,4>()).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, Stride<5,3>()).sum();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PlainObjectType>
|
||||
struct mapstaticmethods_impl<PlainObjectType, true, false>
|
||||
{
|
||||
static void run(const PlainObjectType& m)
|
||||
{
|
||||
Index rows = m.rows(), cols = m.cols();
|
||||
|
||||
int i = internal::random<int>(2,5), j = internal::random<int>(2,5);
|
||||
|
||||
PlainObjectType::Map(ptr, rows, cols).setZero();
|
||||
PlainObjectType::MapAligned(ptr, rows, cols).setZero();
|
||||
PlainObjectType::Map(const_ptr, rows, cols).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, rows, cols).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, rows, cols, InnerStride<>(i)).setZero();
|
||||
PlainObjectType::MapAligned(ptr, rows, cols, InnerStride<>(i)).setZero();
|
||||
PlainObjectType::Map(const_ptr, rows, cols, InnerStride<>(i)).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, rows, cols, InnerStride<>(i)).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, rows, cols, InnerStride<2>()).setZero();
|
||||
PlainObjectType::MapAligned(ptr, rows, cols, InnerStride<3>()).setZero();
|
||||
PlainObjectType::Map(const_ptr, rows, cols, InnerStride<4>()).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, rows, cols, InnerStride<5>()).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, rows, cols, OuterStride<>(i)).setZero();
|
||||
PlainObjectType::MapAligned(ptr, rows, cols, OuterStride<>(i)).setZero();
|
||||
PlainObjectType::Map(const_ptr, rows, cols, OuterStride<>(i)).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, rows, cols, OuterStride<>(i)).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, rows, cols, OuterStride<2>()).setZero();
|
||||
PlainObjectType::MapAligned(ptr, rows, cols, OuterStride<3>()).setZero();
|
||||
PlainObjectType::Map(const_ptr, rows, cols, OuterStride<4>()).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, rows, cols, OuterStride<5>()).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, rows, cols, Stride<Dynamic, Dynamic>(i,j)).setZero();
|
||||
PlainObjectType::MapAligned(ptr, rows, cols, Stride<2,Dynamic>(2,i)).setZero();
|
||||
PlainObjectType::Map(const_ptr, rows, cols, Stride<Dynamic,3>(i,3)).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, rows, cols, Stride<Dynamic, Dynamic>(i,j)).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, rows, cols, Stride<2,3>()).setZero();
|
||||
PlainObjectType::MapAligned(ptr, rows, cols, Stride<3,4>()).setZero();
|
||||
PlainObjectType::Map(const_ptr, rows, cols, Stride<2,4>()).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, rows, cols, Stride<5,3>()).sum();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PlainObjectType>
|
||||
struct mapstaticmethods_impl<PlainObjectType, true, true>
|
||||
{
|
||||
static void run(const PlainObjectType& v)
|
||||
{
|
||||
Index size = v.size();
|
||||
|
||||
int i = internal::random<int>(2,5);
|
||||
|
||||
PlainObjectType::Map(ptr, size).setZero();
|
||||
PlainObjectType::MapAligned(ptr, size).setZero();
|
||||
PlainObjectType::Map(const_ptr, size).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, size).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, size, InnerStride<>(i)).setZero();
|
||||
PlainObjectType::MapAligned(ptr, size, InnerStride<>(i)).setZero();
|
||||
PlainObjectType::Map(const_ptr, size, InnerStride<>(i)).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, size, InnerStride<>(i)).sum();
|
||||
|
||||
PlainObjectType::Map(ptr, size, InnerStride<2>()).setZero();
|
||||
PlainObjectType::MapAligned(ptr, size, InnerStride<3>()).setZero();
|
||||
PlainObjectType::Map(const_ptr, size, InnerStride<4>()).sum();
|
||||
PlainObjectType::MapAligned(const_ptr, size, InnerStride<5>()).sum();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PlainObjectType>
|
||||
void mapstaticmethods(const PlainObjectType& m)
|
||||
{
|
||||
mapstaticmethods_impl<PlainObjectType>::run(m);
|
||||
VERIFY(true); // just to avoid 'unused function' warning
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(mapstaticmethods)
|
||||
{
|
||||
ptr = internal::aligned_new<float>(1000);
|
||||
for(int i = 0; i < 1000; i++) ptr[i] = float(i);
|
||||
|
||||
const_ptr = ptr;
|
||||
|
||||
CALL_SUBTEST_1(( mapstaticmethods(Matrix<float, 1, 1>()) ));
|
||||
CALL_SUBTEST_1(( mapstaticmethods(Vector2f()) ));
|
||||
CALL_SUBTEST_2(( mapstaticmethods(Vector3f()) ));
|
||||
CALL_SUBTEST_2(( mapstaticmethods(Matrix2f()) ));
|
||||
CALL_SUBTEST_3(( mapstaticmethods(Matrix4f()) ));
|
||||
CALL_SUBTEST_3(( mapstaticmethods(Array4f()) ));
|
||||
CALL_SUBTEST_4(( mapstaticmethods(Array3f()) ));
|
||||
CALL_SUBTEST_4(( mapstaticmethods(Array33f()) ));
|
||||
CALL_SUBTEST_5(( mapstaticmethods(Array44f()) ));
|
||||
CALL_SUBTEST_5(( mapstaticmethods(VectorXf(1)) ));
|
||||
CALL_SUBTEST_5(( mapstaticmethods(VectorXf(8)) ));
|
||||
CALL_SUBTEST_6(( mapstaticmethods(MatrixXf(1,1)) ));
|
||||
CALL_SUBTEST_6(( mapstaticmethods(MatrixXf(5,7)) ));
|
||||
CALL_SUBTEST_7(( mapstaticmethods(ArrayXf(1)) ));
|
||||
CALL_SUBTEST_7(( mapstaticmethods(ArrayXf(5)) ));
|
||||
CALL_SUBTEST_8(( mapstaticmethods(ArrayXXf(1,1)) ));
|
||||
CALL_SUBTEST_8(( mapstaticmethods(ArrayXXf(8,6)) ));
|
||||
|
||||
internal::aligned_delete(ptr, 1000);
|
||||
}
|
||||
|
||||
260
libs/eigen/test/mapstride.cpp
Normal file
260
libs/eigen/test/mapstride.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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"
|
||||
|
||||
template<int Alignment,typename VectorType> void map_class_vector(const VectorType& m)
|
||||
{
|
||||
typedef typename VectorType::Scalar Scalar;
|
||||
|
||||
Index size = m.size();
|
||||
|
||||
VectorType v = VectorType::Random(size);
|
||||
|
||||
Index arraysize = 3*size;
|
||||
|
||||
Scalar* a_array = internal::aligned_new<Scalar>(arraysize+1);
|
||||
Scalar* array = a_array;
|
||||
if(Alignment!=Aligned)
|
||||
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);
|
||||
map = v;
|
||||
for(int i = 0; i < size; ++i)
|
||||
{
|
||||
VERIFY(array[3*i] == v[i]);
|
||||
VERIFY(map[i] == v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Map<VectorType, Unaligned, InnerStride<Dynamic> > map(array, size, InnerStride<Dynamic>(2));
|
||||
map = v;
|
||||
for(int i = 0; i < size; ++i)
|
||||
{
|
||||
VERIFY(array[2*i] == v[i]);
|
||||
VERIFY(map[i] == v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
internal::aligned_delete(a_array, arraysize+1);
|
||||
}
|
||||
|
||||
template<int Alignment,typename MatrixType> void map_class_matrix(const MatrixType& _m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
|
||||
Index rows = _m.rows(), cols = _m.cols();
|
||||
|
||||
MatrixType m = MatrixType::Random(rows,cols);
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
|
||||
Index arraysize = 4*(rows+4)*(cols+4);
|
||||
|
||||
Scalar* a_array1 = internal::aligned_new<Scalar>(arraysize+1);
|
||||
Scalar* array1 = a_array1;
|
||||
if(Alignment!=Aligned)
|
||||
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);
|
||||
for(int i = 0; i < m.outerSize(); ++i)
|
||||
for(int j = 0; j < m.innerSize(); ++j)
|
||||
{
|
||||
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
|
||||
};
|
||||
Map<MatrixType, Alignment, OuterStride<OuterStrideAtCompileTime> >
|
||||
map(array, rows, cols, OuterStride<OuterStrideAtCompileTime>(m.innerSize()+4));
|
||||
map = m;
|
||||
VERIFY(map.outerStride() == map.innerSize()+4);
|
||||
for(int i = 0; i < m.outerSize(); ++i)
|
||||
for(int j = 0; j < m.innerSize(); ++j)
|
||||
{
|
||||
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);
|
||||
VERIFY(map.innerStride() == 2);
|
||||
for(int i = 0; i < m.outerSize(); ++i)
|
||||
for(int j = 0; j < m.innerSize(); ++j)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// test inner stride and no outer stride
|
||||
for(int k=0; k<2; ++k)
|
||||
{
|
||||
if(k==1 && (m.innerSize()*2)*m.outerSize() > maxsize2)
|
||||
break;
|
||||
Scalar* array = (k==0 ? array1 : array2);
|
||||
|
||||
Map<MatrixType, Alignment, InnerStride<Dynamic> > map(array, rows, cols, InnerStride<Dynamic>(2));
|
||||
map = m;
|
||||
VERIFY(map.outerStride() == map.innerSize()*2);
|
||||
for(int i = 0; i < m.outerSize(); ++i)
|
||||
for(int j = 0; j < m.innerSize(); ++j)
|
||||
{
|
||||
VERIFY(array[map.innerSize()*i*2+j*2] == 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 negative strides
|
||||
{
|
||||
Matrix<Scalar,Dynamic,1>::Map(a_array1, arraysize+1).setRandom();
|
||||
Index outerstride = m.innerSize()+4;
|
||||
Scalar* array = array1;
|
||||
|
||||
{
|
||||
Map<MatrixType, Alignment, OuterStride<> > map1(array, rows, cols, OuterStride<>( outerstride));
|
||||
Map<MatrixType, Unaligned, OuterStride<> > map2(array+(m.outerSize()-1)*outerstride, rows, cols, OuterStride<>(-outerstride));
|
||||
if(MatrixType::IsRowMajor) VERIFY_IS_APPROX(map1.colwise().reverse(), map2);
|
||||
else VERIFY_IS_APPROX(map1.rowwise().reverse(), map2);
|
||||
}
|
||||
|
||||
{
|
||||
Map<MatrixType, Alignment, OuterStride<> > map1(array, rows, cols, OuterStride<>( outerstride));
|
||||
Map<MatrixType, Unaligned, Stride<Dynamic,Dynamic> > map2(array+(m.outerSize()-1)*outerstride+m.innerSize()-1, rows, cols, Stride<Dynamic,Dynamic>(-outerstride,-1));
|
||||
VERIFY_IS_APPROX(map1.reverse(), map2);
|
||||
}
|
||||
|
||||
{
|
||||
Map<MatrixType, Alignment, OuterStride<> > map1(array, rows, cols, OuterStride<>( outerstride));
|
||||
Map<MatrixType, Unaligned, Stride<Dynamic,-1> > map2(array+(m.outerSize()-1)*outerstride+m.innerSize()-1, rows, cols, Stride<Dynamic,-1>(-outerstride,-1));
|
||||
VERIFY_IS_APPROX(map1.reverse(), map2);
|
||||
}
|
||||
}
|
||||
|
||||
internal::aligned_delete(a_array1, arraysize+1);
|
||||
}
|
||||
|
||||
// Additional tests for inner-stride but no outer-stride
|
||||
template<int>
|
||||
void bug1453()
|
||||
{
|
||||
const int data[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
typedef Matrix<int,Dynamic,Dynamic,RowMajor> RowMatrixXi;
|
||||
typedef Matrix<int,2,3,ColMajor> ColMatrix23i;
|
||||
typedef Matrix<int,3,2,ColMajor> ColMatrix32i;
|
||||
typedef Matrix<int,2,3,RowMajor> RowMatrix23i;
|
||||
typedef Matrix<int,3,2,RowMajor> RowMatrix32i;
|
||||
|
||||
VERIFY_IS_APPROX(MatrixXi::Map(data, 2, 3, InnerStride<2>()), MatrixXi::Map(data, 2, 3, Stride<4,2>()));
|
||||
VERIFY_IS_APPROX(MatrixXi::Map(data, 2, 3, InnerStride<>(2)), MatrixXi::Map(data, 2, 3, Stride<4,2>()));
|
||||
VERIFY_IS_APPROX(MatrixXi::Map(data, 3, 2, InnerStride<2>()), MatrixXi::Map(data, 3, 2, Stride<6,2>()));
|
||||
VERIFY_IS_APPROX(MatrixXi::Map(data, 3, 2, InnerStride<>(2)), MatrixXi::Map(data, 3, 2, Stride<6,2>()));
|
||||
|
||||
VERIFY_IS_APPROX(RowMatrixXi::Map(data, 2, 3, InnerStride<2>()), RowMatrixXi::Map(data, 2, 3, Stride<6,2>()));
|
||||
VERIFY_IS_APPROX(RowMatrixXi::Map(data, 2, 3, InnerStride<>(2)), RowMatrixXi::Map(data, 2, 3, Stride<6,2>()));
|
||||
VERIFY_IS_APPROX(RowMatrixXi::Map(data, 3, 2, InnerStride<2>()), RowMatrixXi::Map(data, 3, 2, Stride<4,2>()));
|
||||
VERIFY_IS_APPROX(RowMatrixXi::Map(data, 3, 2, InnerStride<>(2)), RowMatrixXi::Map(data, 3, 2, Stride<4,2>()));
|
||||
|
||||
VERIFY_IS_APPROX(ColMatrix23i::Map(data, InnerStride<2>()), MatrixXi::Map(data, 2, 3, Stride<4,2>()));
|
||||
VERIFY_IS_APPROX(ColMatrix23i::Map(data, InnerStride<>(2)), MatrixXi::Map(data, 2, 3, Stride<4,2>()));
|
||||
VERIFY_IS_APPROX(ColMatrix32i::Map(data, InnerStride<2>()), MatrixXi::Map(data, 3, 2, Stride<6,2>()));
|
||||
VERIFY_IS_APPROX(ColMatrix32i::Map(data, InnerStride<>(2)), MatrixXi::Map(data, 3, 2, Stride<6,2>()));
|
||||
|
||||
VERIFY_IS_APPROX(RowMatrix23i::Map(data, InnerStride<2>()), RowMatrixXi::Map(data, 2, 3, Stride<6,2>()));
|
||||
VERIFY_IS_APPROX(RowMatrix23i::Map(data, InnerStride<>(2)), RowMatrixXi::Map(data, 2, 3, Stride<6,2>()));
|
||||
VERIFY_IS_APPROX(RowMatrix32i::Map(data, InnerStride<2>()), RowMatrixXi::Map(data, 3, 2, Stride<4,2>()));
|
||||
VERIFY_IS_APPROX(RowMatrix32i::Map(data, InnerStride<>(2)), RowMatrixXi::Map(data, 3, 2, Stride<4,2>()));
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(mapstride)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
int maxn = 3;
|
||||
CALL_SUBTEST_1( map_class_vector<Aligned>(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_1( map_class_vector<Unaligned>(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( map_class_vector<Aligned>(Vector4d()) );
|
||||
CALL_SUBTEST_2( map_class_vector<Unaligned>(Vector4d()) );
|
||||
CALL_SUBTEST_3( map_class_vector<Aligned>(RowVector4f()) );
|
||||
CALL_SUBTEST_3( map_class_vector<Unaligned>(RowVector4f()) );
|
||||
CALL_SUBTEST_4( map_class_vector<Aligned>(VectorXcf(internal::random<int>(1,maxn))) );
|
||||
CALL_SUBTEST_4( map_class_vector<Unaligned>(VectorXcf(internal::random<int>(1,maxn))) );
|
||||
CALL_SUBTEST_5( map_class_vector<Aligned>(VectorXi(internal::random<int>(1,maxn))) );
|
||||
CALL_SUBTEST_5( map_class_vector<Unaligned>(VectorXi(internal::random<int>(1,maxn))) );
|
||||
|
||||
CALL_SUBTEST_1( map_class_matrix<Aligned>(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_1( map_class_matrix<Unaligned>(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( map_class_matrix<Aligned>(Matrix4d()) );
|
||||
CALL_SUBTEST_2( map_class_matrix<Unaligned>(Matrix4d()) );
|
||||
CALL_SUBTEST_3( map_class_matrix<Aligned>(Matrix<float,3,5>()) );
|
||||
CALL_SUBTEST_3( map_class_matrix<Unaligned>(Matrix<float,3,5>()) );
|
||||
CALL_SUBTEST_3( map_class_matrix<Aligned>(Matrix<float,4,8>()) );
|
||||
CALL_SUBTEST_3( map_class_matrix<Unaligned>(Matrix<float,4,8>()) );
|
||||
CALL_SUBTEST_4( map_class_matrix<Aligned>(MatrixXcf(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
|
||||
CALL_SUBTEST_4( map_class_matrix<Unaligned>(MatrixXcf(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
|
||||
CALL_SUBTEST_5( map_class_matrix<Aligned>(MatrixXi(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
|
||||
CALL_SUBTEST_5( map_class_matrix<Unaligned>(MatrixXi(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
|
||||
CALL_SUBTEST_6( map_class_matrix<Aligned>(MatrixXcd(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
|
||||
CALL_SUBTEST_6( map_class_matrix<Unaligned>(MatrixXcd(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
|
||||
|
||||
CALL_SUBTEST_5( bug1453<0>() );
|
||||
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(maxn);
|
||||
}
|
||||
}
|
||||
158
libs/eigen/test/meta.cpp
Normal file
158
libs/eigen/test/meta.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 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"
|
||||
|
||||
template<typename From, typename To>
|
||||
bool check_is_convertible(const From&, const To&)
|
||||
{
|
||||
return internal::is_convertible<From,To>::value;
|
||||
}
|
||||
|
||||
struct FooReturnType {
|
||||
typedef int ReturnType;
|
||||
};
|
||||
|
||||
struct MyInterface {
|
||||
virtual void func() = 0;
|
||||
virtual ~MyInterface() {}
|
||||
};
|
||||
struct MyImpl : public MyInterface {
|
||||
void func() {}
|
||||
};
|
||||
|
||||
EIGEN_DECLARE_TEST(meta)
|
||||
{
|
||||
VERIFY((internal::conditional<(3<4),internal::true_type, internal::false_type>::type::value));
|
||||
VERIFY(( internal::is_same<float,float>::value));
|
||||
VERIFY((!internal::is_same<float,double>::value));
|
||||
VERIFY((!internal::is_same<float,float&>::value));
|
||||
VERIFY((!internal::is_same<float,const float&>::value));
|
||||
|
||||
VERIFY(( internal::is_same<float,internal::remove_all<const float&>::type >::value));
|
||||
VERIFY(( internal::is_same<float,internal::remove_all<const float*>::type >::value));
|
||||
VERIFY(( internal::is_same<float,internal::remove_all<const float*&>::type >::value));
|
||||
VERIFY(( internal::is_same<float,internal::remove_all<float**>::type >::value));
|
||||
VERIFY(( internal::is_same<float,internal::remove_all<float**&>::type >::value));
|
||||
VERIFY(( internal::is_same<float,internal::remove_all<float* const *&>::type >::value));
|
||||
VERIFY(( internal::is_same<float,internal::remove_all<float* const>::type >::value));
|
||||
|
||||
// test add_const
|
||||
VERIFY(( internal::is_same< internal::add_const<float>::type, const float >::value));
|
||||
VERIFY(( internal::is_same< internal::add_const<float*>::type, float* const>::value));
|
||||
VERIFY(( internal::is_same< internal::add_const<float const*>::type, float const* const>::value));
|
||||
VERIFY(( internal::is_same< internal::add_const<float&>::type, float& >::value));
|
||||
|
||||
// test remove_const
|
||||
VERIFY(( internal::is_same< internal::remove_const<float const* const>::type, float const* >::value));
|
||||
VERIFY(( internal::is_same< internal::remove_const<float const*>::type, float const* >::value));
|
||||
VERIFY(( internal::is_same< internal::remove_const<float* const>::type, float* >::value));
|
||||
|
||||
// test add_const_on_value_type
|
||||
VERIFY(( internal::is_same< internal::add_const_on_value_type<float&>::type, float const& >::value));
|
||||
VERIFY(( internal::is_same< internal::add_const_on_value_type<float*>::type, float const* >::value));
|
||||
|
||||
VERIFY(( internal::is_same< internal::add_const_on_value_type<float>::type, const float >::value));
|
||||
VERIFY(( internal::is_same< internal::add_const_on_value_type<const float>::type, const float >::value));
|
||||
|
||||
VERIFY(( internal::is_same< internal::add_const_on_value_type<const float* const>::type, const float* const>::value));
|
||||
VERIFY(( internal::is_same< internal::add_const_on_value_type<float* const>::type, const float* const>::value));
|
||||
|
||||
VERIFY(( internal::is_same<float,internal::remove_reference<float&>::type >::value));
|
||||
VERIFY(( internal::is_same<const float,internal::remove_reference<const float&>::type >::value));
|
||||
VERIFY(( internal::is_same<float,internal::remove_pointer<float*>::type >::value));
|
||||
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));
|
||||
|
||||
|
||||
// is_convertible
|
||||
STATIC_CHECK(( internal::is_convertible<float,double>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<int,double>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<int, short>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<short, int>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<double,int>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<double,std::complex<double> >::value ));
|
||||
STATIC_CHECK((!internal::is_convertible<std::complex<double>,double>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<Array33f,Matrix3f>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<Matrix3f&,Matrix3f>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<Matrix3f&,Matrix3f&>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<Matrix3f&,const Matrix3f&>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<const Matrix3f&,Matrix3f>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<const Matrix3f&,const Matrix3f&>::value ));
|
||||
STATIC_CHECK((!internal::is_convertible<const Matrix3f&,Matrix3f&>::value ));
|
||||
STATIC_CHECK((!internal::is_convertible<const Matrix3f,Matrix3f&>::value ));
|
||||
STATIC_CHECK(!( internal::is_convertible<Matrix3f,Matrix3f&>::value ));
|
||||
|
||||
STATIC_CHECK(!( internal::is_convertible<int,int&>::value ));
|
||||
STATIC_CHECK(( internal::is_convertible<const int,const int& >::value ));
|
||||
|
||||
//STATIC_CHECK((!internal::is_convertible<Matrix3f,Matrix3d>::value )); //does not even compile because the conversion is prevented by a static assertion
|
||||
STATIC_CHECK((!internal::is_convertible<Array33f,int>::value ));
|
||||
STATIC_CHECK((!internal::is_convertible<MatrixXf,float>::value ));
|
||||
{
|
||||
float f = 0.0f;
|
||||
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) ));
|
||||
}
|
||||
|
||||
#if (EIGEN_COMP_GNUC && EIGEN_COMP_GNUC <= 99) \
|
||||
|| (EIGEN_COMP_CLANG && EIGEN_COMP_CLANG <= 909) \
|
||||
|| (EIGEN_COMP_MSVC && EIGEN_COMP_MSVC <=1914)
|
||||
// See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1752,
|
||||
// basically, a fix in the c++ standard breaks our c++98 implementation
|
||||
// of is_convertible for abstract classes.
|
||||
// So the following tests are expected to fail with recent compilers.
|
||||
|
||||
STATIC_CHECK(( !internal::is_convertible<MyInterface, MyImpl>::value ));
|
||||
#if (!EIGEN_COMP_GNUC_STRICT) || (EIGEN_GNUC_AT_LEAST(4,8))
|
||||
// GCC prior to 4.8 fails to compile this test:
|
||||
// error: cannot allocate an object of abstract type 'MyInterface'
|
||||
// In other word, it does not obey SFINAE.
|
||||
// Nevertheless, we don't really care about supporting abstract type as scalar type!
|
||||
STATIC_CHECK(( !internal::is_convertible<MyImpl, MyInterface>::value ));
|
||||
#endif
|
||||
STATIC_CHECK(( internal::is_convertible<MyImpl, const MyInterface&>::value ));
|
||||
|
||||
#endif
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
VERIFY(( check_is_convertible(fix<3>(), i) ));
|
||||
VERIFY((!check_is_convertible(i, fix<DynamicIndex>()) ));
|
||||
}
|
||||
|
||||
|
||||
VERIFY(( internal::has_ReturnType<FooReturnType>::value ));
|
||||
VERIFY(( internal::has_ReturnType<ScalarBinaryOpTraits<int,int> >::value ));
|
||||
VERIFY(( !internal::has_ReturnType<MatrixXf>::value ));
|
||||
VERIFY(( !internal::has_ReturnType<int>::value ));
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
25
libs/eigen/test/metis_support.cpp
Normal file
25
libs/eigen/test/metis_support.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@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_solver.h"
|
||||
#include <Eigen/SparseLU>
|
||||
#include <Eigen/MetisSupport>
|
||||
#include <unsupported/Eigen/SparseExtra>
|
||||
|
||||
template<typename T> void test_metis_T()
|
||||
{
|
||||
SparseLU<SparseMatrix<T, ColMajor>, MetisOrdering<int> > sparselu_metis;
|
||||
|
||||
check_sparse_square_solving(sparselu_metis);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(metis_support)
|
||||
{
|
||||
CALL_SUBTEST_1(test_metis_T<double>());
|
||||
}
|
||||
46
libs/eigen/test/miscmatrices.cpp
Normal file
46
libs/eigen/test/miscmatrices.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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;
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
Index r = internal::random<Index>(0, rows-1), r2 = internal::random<Index>(0, rows-1), c = internal::random<Index>(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));
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(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)) );
|
||||
}
|
||||
}
|
||||
329
libs/eigen/test/mixingtypes.cpp
Normal file
329
libs/eigen/test/mixingtypes.cpp
Normal file
@@ -0,0 +1,329 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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
|
||||
// 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_7)
|
||||
|
||||
#ifndef EIGEN_NO_STATIC_ASSERT
|
||||
#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
|
||||
#endif
|
||||
|
||||
// ignore double-promotion diagnostic for clang and gcc, if we check for static assertion anyway:
|
||||
// TODO do the same for MSVC?
|
||||
#if defined(__clang__)
|
||||
# if (__clang_major__ * 100 + __clang_minor__) >= 308
|
||||
# pragma clang diagnostic ignored "-Wdouble-promotion"
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
// TODO is there a minimal GCC version for this? At least g++-4.7 seems to be fine with this.
|
||||
# pragma GCC diagnostic ignored "-Wdouble-promotion"
|
||||
#endif
|
||||
|
||||
#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 raise_assertion(Index size = SizeAtCompileType)
|
||||
{
|
||||
// VERIFY_RAISES_ASSERT(mf+md); // does not even compile
|
||||
Matrix<float, SizeAtCompileType, 1> vf; vf.setRandom(size);
|
||||
Matrix<double, SizeAtCompileType, 1> vd; vd.setRandom(size);
|
||||
VERIFY_RAISES_ASSERT(vf=vd);
|
||||
VERIFY_RAISES_ASSERT(vf+=vd);
|
||||
VERIFY_RAISES_ASSERT(vf-=vd);
|
||||
VERIFY_RAISES_ASSERT(vd=vf);
|
||||
VERIFY_RAISES_ASSERT(vd+=vf);
|
||||
VERIFY_RAISES_ASSERT(vd-=vf);
|
||||
|
||||
// vd.asDiagonal() * mf; // does not even compile
|
||||
// vcd.asDiagonal() * mf; // does not even compile
|
||||
|
||||
#if 0 // we get other compilation errors here than just static asserts
|
||||
VERIFY_RAISES_ASSERT(vd.dot(vf));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
|
||||
{
|
||||
typedef std::complex<float> CF;
|
||||
typedef std::complex<double> CD;
|
||||
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 = 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);
|
||||
Vec_cd vcd = vcf.template cast<complex<double> >();
|
||||
float sf = internal::random<float>();
|
||||
double sd = internal::random<double>();
|
||||
complex<float> scf = internal::random<complex<float> >();
|
||||
complex<double> scd = internal::random<complex<double> >();
|
||||
|
||||
mf+mf;
|
||||
|
||||
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) sd = internal::random<double>();
|
||||
while(std::abs(scf)<epsf) scf = internal::random<CF>();
|
||||
while(std::abs(scd)<epsd) scd = internal::random<CD>();
|
||||
|
||||
// check scalar products
|
||||
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);
|
||||
VERIFY_IS_APPROX(vcf.dot(vf), vcf.dot(vf.template cast<complex<float> >()));
|
||||
|
||||
// check diagonal product
|
||||
VERIFY_IS_APPROX(vf.asDiagonal() * mcf, vf.template cast<complex<float> >().asDiagonal() * mcf);
|
||||
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());
|
||||
|
||||
// check inner product
|
||||
VERIFY_IS_APPROX((vf.transpose() * vcf).value(), (vf.template cast<complex<float> >().transpose() * vcf).value());
|
||||
|
||||
// check outer product
|
||||
VERIFY_IS_APPROX((vf * vcf.transpose()).eval(), (vf.template cast<complex<float> >() * vcf.transpose()).eval());
|
||||
|
||||
// coeff wise product
|
||||
|
||||
VERIFY_IS_APPROX((vf * vcf.transpose()).eval(), (vf.template cast<complex<float> >() * vcf.transpose()).eval());
|
||||
|
||||
Mat_cd mcd2 = mcd;
|
||||
VERIFY_IS_APPROX(mcd.array() *= md.array(), mcd2.array() *= md.array().template cast<std::complex<double> >());
|
||||
|
||||
// check matrix-matrix products
|
||||
VERIFY_IS_APPROX(sd*md*mcd, (sd*md).template cast<CD>().eval()*mcd);
|
||||
VERIFY_IS_APPROX(sd*mcd*md, sd*mcd*md.template cast<CD>());
|
||||
VERIFY_IS_APPROX(scd*md*mcd, scd*md.template cast<CD>().eval()*mcd);
|
||||
VERIFY_IS_APPROX(scd*mcd*md, scd*mcd*md.template cast<CD>());
|
||||
|
||||
VERIFY_IS_APPROX(sf*mf*mcf, sf*mf.template cast<CF>()*mcf);
|
||||
VERIFY_IS_APPROX(sf*mcf*mf, sf*mcf*mf.template cast<CF>());
|
||||
VERIFY_IS_APPROX(scf*mf*mcf, scf*mf.template cast<CF>()*mcf);
|
||||
VERIFY_IS_APPROX(scf*mcf*mf, scf*mcf*mf.template cast<CF>());
|
||||
|
||||
VERIFY_IS_APPROX(sd*md.adjoint()*mcd, (sd*md).template cast<CD>().eval().adjoint()*mcd);
|
||||
VERIFY_IS_APPROX(sd*mcd.adjoint()*md, sd*mcd.adjoint()*md.template cast<CD>());
|
||||
VERIFY_IS_APPROX(sd*md.adjoint()*mcd.adjoint(), (sd*md).template cast<CD>().eval().adjoint()*mcd.adjoint());
|
||||
VERIFY_IS_APPROX(sd*mcd.adjoint()*md.adjoint(), sd*mcd.adjoint()*md.template cast<CD>().adjoint());
|
||||
VERIFY_IS_APPROX(sd*md*mcd.adjoint(), (sd*md).template cast<CD>().eval()*mcd.adjoint());
|
||||
VERIFY_IS_APPROX(sd*mcd*md.adjoint(), sd*mcd*md.template cast<CD>().adjoint());
|
||||
|
||||
VERIFY_IS_APPROX(sf*mf.adjoint()*mcf, (sf*mf).template cast<CF>().eval().adjoint()*mcf);
|
||||
VERIFY_IS_APPROX(sf*mcf.adjoint()*mf, sf*mcf.adjoint()*mf.template cast<CF>());
|
||||
VERIFY_IS_APPROX(sf*mf.adjoint()*mcf.adjoint(), (sf*mf).template cast<CF>().eval().adjoint()*mcf.adjoint());
|
||||
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>());
|
||||
VERIFY_IS_APPROX(scf*mcf*vf,scf*mcf*vf.template cast<CF>());
|
||||
|
||||
VERIFY_IS_APPROX(sf*vcf.adjoint()*mf, sf*vcf.adjoint()*mf.template cast<CF>().eval());
|
||||
VERIFY_IS_APPROX(scf*vcf.adjoint()*mf, scf*vcf.adjoint()*mf.template cast<CF>().eval());
|
||||
VERIFY_IS_APPROX(sf*vf.adjoint()*mcf, sf*vf.adjoint().template cast<CF>().eval()*mcf);
|
||||
VERIFY_IS_APPROX(scf*vf.adjoint()*mcf, scf*vf.adjoint().template cast<CF>().eval()*mcf);
|
||||
|
||||
VERIFY_IS_APPROX(sd*md*vcd, (sd*md).template cast<CD>().eval()*vcd);
|
||||
VERIFY_IS_APPROX(scd*md*vcd,(scd*md.template cast<CD>()).eval()*vcd);
|
||||
VERIFY_IS_APPROX(sd*mcd*vd, sd*mcd*vd.template cast<CD>().eval());
|
||||
VERIFY_IS_APPROX(scd*mcd*vd,scd*mcd*vd.template cast<CD>().eval());
|
||||
|
||||
VERIFY_IS_APPROX(sd*vcd.adjoint()*md, sd*vcd.adjoint()*md.template cast<CD>().eval());
|
||||
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>()) );
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(mixingtypes)
|
||||
{
|
||||
g_called = false; // Silence -Wunneeded-internal-declaration.
|
||||
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)));
|
||||
CALL_SUBTEST_7(raise_assertion<Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)));
|
||||
}
|
||||
CALL_SUBTEST_7(raise_assertion<0>());
|
||||
CALL_SUBTEST_7(raise_assertion<3>());
|
||||
CALL_SUBTEST_7(raise_assertion<4>());
|
||||
CALL_SUBTEST_7(raise_assertion<Dynamic>(0));
|
||||
}
|
||||
24
libs/eigen/test/mpl2only.cpp
Normal file
24
libs/eigen/test/mpl2only.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// 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/.
|
||||
|
||||
#ifndef EIGEN_MPL2_ONLY
|
||||
#define EIGEN_MPL2_ONLY
|
||||
#endif
|
||||
#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;
|
||||
}
|
||||
37
libs/eigen/test/nestbyvalue.cpp
Normal file
37
libs/eigen/test/nestbyvalue.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2019 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"
|
||||
|
||||
typedef NestByValue<MatrixXd> CpyMatrixXd;
|
||||
typedef CwiseBinaryOp<internal::scalar_sum_op<double,double>,const CpyMatrixXd,const CpyMatrixXd> XprType;
|
||||
|
||||
XprType get_xpr_with_temps(const MatrixXd& a)
|
||||
{
|
||||
MatrixXd t1 = a.rowwise().reverse();
|
||||
MatrixXd t2 = a+a;
|
||||
return t1.nestByValue() + t2.nestByValue();
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(nestbyvalue)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
Index rows = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
Index cols = internal::random<Index>(1,EIGEN_TEST_MAX_SIZE);
|
||||
MatrixXd a = MatrixXd(rows,cols);
|
||||
nb_temporaries = 0;
|
||||
XprType x = get_xpr_with_temps(a);
|
||||
VERIFY_IS_EQUAL(nb_temporaries,6);
|
||||
MatrixXd b = x;
|
||||
VERIFY_IS_EQUAL(nb_temporaries,6+1);
|
||||
VERIFY_IS_APPROX(b, a.rowwise().reverse().eval() + (a+a).eval());
|
||||
}
|
||||
}
|
||||
107
libs/eigen/test/nesting_ops.cpp
Normal file
107
libs/eigen/test/nesting_ops.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// 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 <int N, typename XprType>
|
||||
void use_n_times(const XprType &xpr)
|
||||
{
|
||||
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));
|
||||
|
||||
// The only intention of these tests is to ensure that this code does
|
||||
// not trigger any asserts or segmentation faults... more to come.
|
||||
VERIFY_IS_APPROX( (m.transpose() * m).diagonal().sum(), (m.transpose() * m).diagonal().sum() );
|
||||
VERIFY_IS_APPROX( (m.transpose() * m).diagonal().array().abs().sum(), (m.transpose() * m).diagonal().array().abs().sum() );
|
||||
|
||||
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) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EIGEN_DECLARE_TEST(nesting_ops)
|
||||
{
|
||||
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)
|
||||
}
|
||||
228
libs/eigen/test/nomalloc.cpp
Normal file
228
libs/eigen/test/nomalloc.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
// 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/.
|
||||
|
||||
// discard stack allocation as that too bypasses malloc
|
||||
#define EIGEN_STACK_ALLOCATION_LIMIT 0
|
||||
// heap allocation will raise an assert if enabled at runtime
|
||||
#define EIGEN_RUNTIME_NO_MALLOC
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/Cholesky>
|
||||
#include <Eigen/Eigenvalues>
|
||||
#include <Eigen/LU>
|
||||
#include <Eigen/QR>
|
||||
#include <Eigen/SVD>
|
||||
|
||||
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;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>();
|
||||
|
||||
Index r = internal::random<Index>(0, rows-1),
|
||||
c = internal::random<Index>(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.cwiseProduct(m1.block(0,0,rows,cols)), (m1.array()*m1.array()).matrix());
|
||||
VERIFY_IS_APPROX((m1*m1.transpose())*m2, m1*(m1.transpose()*m2));
|
||||
|
||||
m2.col(0).noalias() = m1 * m1.col(0);
|
||||
m2.col(0).noalias() -= m1.adjoint() * m1.col(0);
|
||||
m2.col(0).noalias() -= m1 * m1.row(0).adjoint();
|
||||
m2.col(0).noalias() -= m1.adjoint() * m1.row(0).adjoint();
|
||||
|
||||
m2.row(0).noalias() = m1.row(0) * m1;
|
||||
m2.row(0).noalias() -= m1.row(0) * m1.adjoint();
|
||||
m2.row(0).noalias() -= m1.col(0).adjoint() * m1;
|
||||
m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint();
|
||||
VERIFY_IS_APPROX(m2,m2);
|
||||
|
||||
m2.col(0).noalias() = m1.template triangularView<Upper>() * m1.col(0);
|
||||
m2.col(0).noalias() -= m1.adjoint().template triangularView<Upper>() * m1.col(0);
|
||||
m2.col(0).noalias() -= m1.template triangularView<Upper>() * m1.row(0).adjoint();
|
||||
m2.col(0).noalias() -= m1.adjoint().template triangularView<Upper>() * m1.row(0).adjoint();
|
||||
|
||||
m2.row(0).noalias() = m1.row(0) * m1.template triangularView<Upper>();
|
||||
m2.row(0).noalias() -= m1.row(0) * m1.adjoint().template triangularView<Upper>();
|
||||
m2.row(0).noalias() -= m1.col(0).adjoint() * m1.template triangularView<Upper>();
|
||||
m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint().template triangularView<Upper>();
|
||||
VERIFY_IS_APPROX(m2,m2);
|
||||
|
||||
m2.col(0).noalias() = m1.template selfadjointView<Upper>() * m1.col(0);
|
||||
m2.col(0).noalias() -= m1.adjoint().template selfadjointView<Upper>() * m1.col(0);
|
||||
m2.col(0).noalias() -= m1.template selfadjointView<Upper>() * m1.row(0).adjoint();
|
||||
m2.col(0).noalias() -= m1.adjoint().template selfadjointView<Upper>() * m1.row(0).adjoint();
|
||||
|
||||
m2.row(0).noalias() = m1.row(0) * m1.template selfadjointView<Upper>();
|
||||
m2.row(0).noalias() -= m1.row(0) * m1.adjoint().template selfadjointView<Upper>();
|
||||
m2.row(0).noalias() -= m1.col(0).adjoint() * m1.template selfadjointView<Upper>();
|
||||
m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint().template selfadjointView<Upper>();
|
||||
VERIFY_IS_APPROX(m2,m2);
|
||||
|
||||
m2.template selfadjointView<Lower>().rankUpdate(m1.col(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
|
||||
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>
|
||||
void ctms_decompositions()
|
||||
{
|
||||
const int maxSize = 16;
|
||||
const int size = 12;
|
||||
|
||||
typedef Eigen::Matrix<Scalar,
|
||||
Eigen::Dynamic, Eigen::Dynamic,
|
||||
0,
|
||||
maxSize, maxSize> Matrix;
|
||||
|
||||
typedef Eigen::Matrix<Scalar,
|
||||
Eigen::Dynamic, 1,
|
||||
0,
|
||||
maxSize, 1> Vector;
|
||||
|
||||
typedef Eigen::Matrix<std::complex<Scalar>,
|
||||
Eigen::Dynamic, Eigen::Dynamic,
|
||||
0,
|
||||
maxSize, maxSize> ComplexMatrix;
|
||||
|
||||
const Matrix A(Matrix::Random(size, size)), B(Matrix::Random(size, size));
|
||||
Matrix X(size,size);
|
||||
const ComplexMatrix complexA(ComplexMatrix::Random(size, size));
|
||||
const Matrix saA = A.adjoint() * A;
|
||||
const Vector b(Vector::Random(size));
|
||||
Vector x(size);
|
||||
|
||||
// Cholesky module
|
||||
Eigen::LLT<Matrix> LLT; LLT.compute(A);
|
||||
X = LLT.solve(B);
|
||||
x = LLT.solve(b);
|
||||
Eigen::LDLT<Matrix> LDLT; LDLT.compute(A);
|
||||
X = LDLT.solve(B);
|
||||
x = LDLT.solve(b);
|
||||
|
||||
// Eigenvalues module
|
||||
Eigen::HessenbergDecomposition<ComplexMatrix> hessDecomp; hessDecomp.compute(complexA);
|
||||
Eigen::ComplexSchur<ComplexMatrix> cSchur(size); cSchur.compute(complexA);
|
||||
Eigen::ComplexEigenSolver<ComplexMatrix> cEigSolver; cEigSolver.compute(complexA);
|
||||
Eigen::EigenSolver<Matrix> eigSolver; eigSolver.compute(A);
|
||||
Eigen::SelfAdjointEigenSolver<Matrix> saEigSolver(size); saEigSolver.compute(saA);
|
||||
Eigen::Tridiagonalization<Matrix> tridiag; tridiag.compute(saA);
|
||||
|
||||
// LU module
|
||||
Eigen::PartialPivLU<Matrix> ppLU; ppLU.compute(A);
|
||||
X = ppLU.solve(B);
|
||||
x = ppLU.solve(b);
|
||||
Eigen::FullPivLU<Matrix> fpLU; fpLU.compute(A);
|
||||
X = fpLU.solve(B);
|
||||
x = fpLU.solve(b);
|
||||
|
||||
// QR module
|
||||
Eigen::HouseholderQR<Matrix> hQR; hQR.compute(A);
|
||||
X = hQR.solve(B);
|
||||
x = hQR.solve(b);
|
||||
Eigen::ColPivHouseholderQR<Matrix> cpQR; cpQR.compute(A);
|
||||
X = cpQR.solve(B);
|
||||
x = cpQR.solve(b);
|
||||
Eigen::FullPivHouseholderQR<Matrix> fpQR; fpQR.compute(A);
|
||||
// FIXME X = fpQR.solve(B);
|
||||
x = fpQR.solve(b);
|
||||
|
||||
// SVD module
|
||||
Eigen::JacobiSVD<Matrix> jSVD; jSVD.compute(A, ComputeFullU | ComputeFullV);
|
||||
}
|
||||
|
||||
void test_zerosized() {
|
||||
// default constructors:
|
||||
Eigen::MatrixXd A;
|
||||
Eigen::VectorXd v;
|
||||
// explicit zero-sized:
|
||||
Eigen::ArrayXXd A0(0,0);
|
||||
Eigen::ArrayXd v0(0);
|
||||
|
||||
// assigning empty objects to each other:
|
||||
A=A0;
|
||||
v=v0;
|
||||
}
|
||||
|
||||
template<typename MatrixType> void test_reference(const MatrixType& m) {
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
enum { Flag = MatrixType::IsRowMajor ? Eigen::RowMajor : Eigen::ColMajor};
|
||||
enum { TransposeFlag = !MatrixType::IsRowMajor ? Eigen::RowMajor : Eigen::ColMajor};
|
||||
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 MatrixX > Ref;
|
||||
typedef Eigen::Ref<const MatrixXT > RefT;
|
||||
|
||||
Ref r1(m);
|
||||
Ref r2(m.block(rows/3, cols/4, rows/2, cols/2));
|
||||
RefT r3(m.transpose());
|
||||
RefT r4(m.topLeftCorner(rows/2, cols/2).transpose());
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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>()) );
|
||||
CALL_SUBTEST_2(nomalloc(Matrix4d()) );
|
||||
CALL_SUBTEST_3(nomalloc(Matrix<float,32,32>()) );
|
||||
|
||||
// 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));
|
||||
}
|
||||
341
libs/eigen/test/nullary.cpp
Normal file
341
libs/eigen/test/nullary.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// 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
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType>
|
||||
bool equalsIdentity(const MatrixType& A)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
Scalar zero = static_cast<Scalar>(0);
|
||||
|
||||
bool offDiagOK = true;
|
||||
for (Index i = 0; i < A.rows(); ++i) {
|
||||
for (Index j = i+1; j < A.cols(); ++j) {
|
||||
offDiagOK = offDiagOK && (A(i,j) == zero);
|
||||
}
|
||||
}
|
||||
for (Index i = 0; i < A.rows(); ++i) {
|
||||
for (Index j = 0; j < (std::min)(i, A.cols()); ++j) {
|
||||
offDiagOK = offDiagOK && (A(i,j) == zero);
|
||||
}
|
||||
}
|
||||
|
||||
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 VectorType::Scalar Scalar;
|
||||
typedef typename VectorType::RealScalar RealScalar;
|
||||
|
||||
const Index size = base.size();
|
||||
|
||||
Scalar high = internal::random<Scalar>(-500,500);
|
||||
Scalar low = (size == 1 ? high : internal::random<Scalar>(-500,500));
|
||||
if (numext::real(low)>numext::real(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)/RealScalar(size-1));
|
||||
|
||||
// check whether the result yields what we expect it to do
|
||||
VectorType m(base);
|
||||
m.setLinSpaced(size,low,high);
|
||||
|
||||
if(!NumTraits<Scalar>::IsInteger)
|
||||
{
|
||||
VectorType n(size);
|
||||
for (int i=0; i<size; ++i)
|
||||
n(i) = low+RealScalar(i)*step;
|
||||
VERIFY_IS_APPROX(m,n);
|
||||
|
||||
CALL_SUBTEST( check_extremity_accuracy(m, low, high) );
|
||||
}
|
||||
|
||||
RealScalar range_length = numext::real(high-low);
|
||||
if((!NumTraits<Scalar>::IsInteger) || (range_length>=size && (Index(range_length)%(size-1))==0) || (Index(range_length+1)<size && (size%Index(range_length+1))==0))
|
||||
{
|
||||
VectorType n(size);
|
||||
if((!NumTraits<Scalar>::IsInteger) || (range_length>=size))
|
||||
for (int i=0; i<size; ++i)
|
||||
n(i) = size==1 ? low : (low + ((high-low)*Scalar(i))/RealScalar(size-1));
|
||||
else
|
||||
for (int i=0; i<size; ++i)
|
||||
n(i) = size==1 ? low : low + Scalar((double(range_length+1)*double(i))/double(size));
|
||||
VERIFY_IS_APPROX(m,n);
|
||||
|
||||
// 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) );
|
||||
}
|
||||
|
||||
VERIFY( numext::real(m(m.size()-1)) <= numext::real(high) );
|
||||
VERIFY( (m.array().real() <= numext::real(high)).all() );
|
||||
VERIFY( (m.array().real() >= numext::real(low)).all() );
|
||||
|
||||
|
||||
VERIFY( numext::real(m(m.size()-1)) >= numext::real(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);
|
||||
Matrix<Scalar,1,Dynamic> col_vector(size);
|
||||
row_vector.setLinSpaced(size,low,high);
|
||||
col_vector.setLinSpaced(size,low,high);
|
||||
// when using the extended precision (e.g., FPU) the relative error might exceed 1 bit
|
||||
// when computing the squared sum in isApprox, thus the 2x factor.
|
||||
VERIFY( row_vector.isApprox(col_vector.transpose(), RealScalar(2)*NumTraits<Scalar>::epsilon()));
|
||||
|
||||
Matrix<Scalar,Dynamic,1> size_changer(size+50);
|
||||
size_changer.setLinSpaced(size,low,high);
|
||||
VERIFY( size_changer.size() == size );
|
||||
|
||||
typedef Matrix<Scalar,1,1> ScalarMatrix;
|
||||
ScalarMatrix scalar;
|
||||
scalar.setLinSpaced(1,low,high);
|
||||
VERIFY_IS_APPROX( scalar, ScalarMatrix::Constant(high) );
|
||||
VERIFY_IS_APPROX( ScalarMatrix::LinSpaced(1,low,high), ScalarMatrix::Constant(high) );
|
||||
|
||||
// regression test for bug 526 (linear vectorized transversal)
|
||||
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-RealScalar(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-RealScalar(1)).sum(),Scalar(0));
|
||||
}
|
||||
|
||||
m.setLinSpaced(n0,0,Scalar(n0-1));
|
||||
VERIFY(m.size()==n0);
|
||||
m.setLinSpaced(n0,low,low-RealScalar(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,low+Scalar(size-1)), VectorType::LinSpaced(size,low+Scalar(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,low+Scalar((size-1)*k)), VectorType::LinSpaced(size,low+Scalar((size-1)*k),low).reverse() );
|
||||
// Check negative divisor path:
|
||||
for(Index k=1; k<5; ++k)
|
||||
VERIFY_IS_APPROX( VectorType::LinSpaced(size*k,low,low+Scalar(size-1)), VectorType::LinSpaced(size*k,low+Scalar(size-1),low).reverse() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test setUnit()
|
||||
if(m.size()>0)
|
||||
{
|
||||
for(Index k=0; k<10; ++k)
|
||||
{
|
||||
Index i = internal::random<Index>(0,m.size()-1);
|
||||
m.setUnit(i);
|
||||
VERIFY_IS_APPROX( m, VectorType::Unit(m.size(), i) );
|
||||
}
|
||||
if(VectorType::SizeAtCompileTime==Dynamic)
|
||||
{
|
||||
Index i = internal::random<Index>(0,2*m.size()-1);
|
||||
m.setUnit(2*m.size(),i);
|
||||
VERIFY_IS_APPROX( m, VectorType::Unit(m.size(),i) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
void testMatrixType(const MatrixType& m)
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
template<int>
|
||||
void bug79()
|
||||
{
|
||||
// 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() );
|
||||
}
|
||||
|
||||
template<int>
|
||||
void bug1630()
|
||||
{
|
||||
Array4d x4 = Array4d::LinSpaced(0.0, 1.0);
|
||||
Array3d x3(Array4d::LinSpaced(0.0, 1.0).head(3));
|
||||
VERIFY_IS_APPROX(x4.head(3), x3);
|
||||
}
|
||||
|
||||
template<int>
|
||||
void nullary_overflow()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
template<int>
|
||||
void nullary_internal_logic()
|
||||
{
|
||||
// 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> >::value ));
|
||||
VERIFY(( internal::has_unary_operator<internal::linspaced_op<float> >::value ));
|
||||
VERIFY(( !internal::has_binary_operator<internal::linspaced_op<float> >::value ));
|
||||
VERIFY(( internal::functor_has_linear_access<internal::linspaced_op<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> >::value ));
|
||||
VERIFY(( internal::has_unary_operator<internal::linspaced_op<int> >::value ));
|
||||
VERIFY(( !internal::has_binary_operator<internal::linspaced_op<int> >::value ));
|
||||
VERIFY(( internal::functor_has_linear_access<internal::linspaced_op<int> >::ret ));
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(nullary)
|
||||
{
|
||||
CALL_SUBTEST_1( testMatrixType(Matrix2d()) );
|
||||
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*10; i++) {
|
||||
CALL_SUBTEST_3( testVectorType(VectorXcd(internal::random<int>(1,30000))) );
|
||||
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,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>()) );
|
||||
}
|
||||
|
||||
CALL_SUBTEST_6( bug79<0>() );
|
||||
CALL_SUBTEST_6( bug1630<0>() );
|
||||
CALL_SUBTEST_9( nullary_overflow<0>() );
|
||||
CALL_SUBTEST_10( nullary_internal_logic<0>() );
|
||||
}
|
||||
90
libs/eigen/test/num_dimensions.cpp
Normal file
90
libs/eigen/test/num_dimensions.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2018 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/SparseCore>
|
||||
|
||||
template<int ExpectedDim,typename Xpr>
|
||||
void check_dim(const Xpr& ) {
|
||||
STATIC_CHECK( Xpr::NumDimensions == ExpectedDim );
|
||||
}
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
template<template <typename,int,int> class Object>
|
||||
void map_num_dimensions()
|
||||
{
|
||||
typedef Object<double, 1, 1> ArrayScalarType;
|
||||
typedef Object<double, 2, 1> ArrayVectorType;
|
||||
typedef Object<double, 1, 2> TransposeArrayVectorType;
|
||||
typedef Object<double, 2, 2> ArrayType;
|
||||
typedef Object<double, Eigen::Dynamic, 1> DynamicArrayVectorType;
|
||||
typedef Object<double, 1, Eigen::Dynamic> DynamicTransposeArrayVectorType;
|
||||
typedef Object<double, Eigen::Dynamic, Eigen::Dynamic> DynamicArrayType;
|
||||
|
||||
STATIC_CHECK(ArrayScalarType::NumDimensions == 0);
|
||||
STATIC_CHECK(ArrayVectorType::NumDimensions == 1);
|
||||
STATIC_CHECK(TransposeArrayVectorType::NumDimensions == 1);
|
||||
STATIC_CHECK(ArrayType::NumDimensions == 2);
|
||||
STATIC_CHECK(DynamicArrayVectorType::NumDimensions == 1);
|
||||
STATIC_CHECK(DynamicTransposeArrayVectorType::NumDimensions == 1);
|
||||
STATIC_CHECK(DynamicArrayType::NumDimensions == 2);
|
||||
|
||||
typedef Eigen::Map<ArrayScalarType> ArrayScalarMap;
|
||||
typedef Eigen::Map<ArrayVectorType> ArrayVectorMap;
|
||||
typedef Eigen::Map<TransposeArrayVectorType> TransposeArrayVectorMap;
|
||||
typedef Eigen::Map<ArrayType> ArrayMap;
|
||||
typedef Eigen::Map<DynamicArrayVectorType> DynamicArrayVectorMap;
|
||||
typedef Eigen::Map<DynamicTransposeArrayVectorType> DynamicTransposeArrayVectorMap;
|
||||
typedef Eigen::Map<DynamicArrayType> DynamicArrayMap;
|
||||
|
||||
STATIC_CHECK(ArrayScalarMap::NumDimensions == 0);
|
||||
STATIC_CHECK(ArrayVectorMap::NumDimensions == 1);
|
||||
STATIC_CHECK(TransposeArrayVectorMap::NumDimensions == 1);
|
||||
STATIC_CHECK(ArrayMap::NumDimensions == 2);
|
||||
STATIC_CHECK(DynamicArrayVectorMap::NumDimensions == 1);
|
||||
STATIC_CHECK(DynamicTransposeArrayVectorMap::NumDimensions == 1);
|
||||
STATIC_CHECK(DynamicArrayMap::NumDimensions == 2);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Rows, int Cols>
|
||||
using TArray = Array<Scalar,Rows,Cols>;
|
||||
|
||||
template<typename Scalar, int Rows, int Cols>
|
||||
using TMatrix = Matrix<Scalar,Rows,Cols>;
|
||||
|
||||
#endif
|
||||
|
||||
EIGEN_DECLARE_TEST(num_dimensions)
|
||||
{
|
||||
int n = 10;
|
||||
ArrayXXd A(n,n);
|
||||
CALL_SUBTEST( check_dim<2>(A) );
|
||||
CALL_SUBTEST( check_dim<2>(A.block(1,1,2,2)) );
|
||||
CALL_SUBTEST( check_dim<1>(A.col(1)) );
|
||||
CALL_SUBTEST( check_dim<1>(A.row(1)) );
|
||||
|
||||
MatrixXd M(n,n);
|
||||
CALL_SUBTEST( check_dim<0>(M.row(1)*M.col(1)) );
|
||||
|
||||
SparseMatrix<double> S(n,n);
|
||||
CALL_SUBTEST( check_dim<2>(S) );
|
||||
CALL_SUBTEST( check_dim<2>(S.block(1,1,2,2)) );
|
||||
CALL_SUBTEST( check_dim<1>(S.col(1)) );
|
||||
CALL_SUBTEST( check_dim<1>(S.row(1)) );
|
||||
|
||||
SparseVector<double> s(n);
|
||||
CALL_SUBTEST( check_dim<1>(s) );
|
||||
CALL_SUBTEST( check_dim<1>(s.head(2)) );
|
||||
|
||||
|
||||
#if EIGEN_HAS_CXX11
|
||||
CALL_SUBTEST( map_num_dimensions<TArray>() );
|
||||
CALL_SUBTEST( map_num_dimensions<TMatrix>() );
|
||||
#endif
|
||||
}
|
||||
275
libs/eigen/test/numext.cpp
Normal file
275
libs/eigen/test/numext.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
// 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/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename T, typename U>
|
||||
bool check_if_equal_or_nans(const T& actual, const U& expected) {
|
||||
return ((actual == expected) || ((numext::isnan)(actual) && (numext::isnan)(expected)));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
bool check_if_equal_or_nans(const std::complex<T>& actual, const std::complex<U>& expected) {
|
||||
return check_if_equal_or_nans(numext::real(actual), numext::real(expected))
|
||||
&& check_if_equal_or_nans(numext::imag(actual), numext::imag(expected));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
bool test_is_equal_or_nans(const T& actual, const U& expected)
|
||||
{
|
||||
if (check_if_equal_or_nans(actual, expected)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// false:
|
||||
std::cerr
|
||||
<< "\n actual = " << actual
|
||||
<< "\n expected = " << expected << "\n\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
#define VERIFY_IS_EQUAL_OR_NANS(a, b) VERIFY(test_is_equal_or_nans(a, b))
|
||||
|
||||
template<typename T>
|
||||
void check_abs() {
|
||||
typedef typename NumTraits<T>::Real Real;
|
||||
Real zero(0);
|
||||
|
||||
if(NumTraits<T>::IsSigned)
|
||||
VERIFY_IS_EQUAL(numext::abs(-T(1)), T(1));
|
||||
VERIFY_IS_EQUAL(numext::abs(T(0)), T(0));
|
||||
VERIFY_IS_EQUAL(numext::abs(T(1)), T(1));
|
||||
|
||||
for(int k=0; k<100; ++k)
|
||||
{
|
||||
T x = internal::random<T>();
|
||||
if(!internal::is_same<T,bool>::value)
|
||||
x = x/Real(2);
|
||||
if(NumTraits<T>::IsSigned)
|
||||
{
|
||||
VERIFY_IS_EQUAL(numext::abs(x), numext::abs(-x));
|
||||
VERIFY( numext::abs(-x) >= zero );
|
||||
}
|
||||
VERIFY( numext::abs(x) >= zero );
|
||||
VERIFY_IS_APPROX( numext::abs2(x), numext::abs2(numext::abs(x)) );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void check_arg() {
|
||||
typedef typename NumTraits<T>::Real Real;
|
||||
VERIFY_IS_EQUAL(numext::abs(T(0)), T(0));
|
||||
VERIFY_IS_EQUAL(numext::abs(T(1)), T(1));
|
||||
|
||||
for(int k=0; k<100; ++k)
|
||||
{
|
||||
T x = internal::random<T>();
|
||||
Real y = numext::arg(x);
|
||||
VERIFY_IS_APPROX( y, std::arg(x) );
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct check_sqrt_impl {
|
||||
static void run() {
|
||||
for (int i=0; i<1000; ++i) {
|
||||
const T x = numext::abs(internal::random<T>());
|
||||
const T sqrtx = numext::sqrt(x);
|
||||
VERIFY_IS_APPROX(sqrtx*sqrtx, x);
|
||||
}
|
||||
|
||||
// Corner cases.
|
||||
const T zero = T(0);
|
||||
const T one = T(1);
|
||||
const T inf = std::numeric_limits<T>::infinity();
|
||||
const T nan = std::numeric_limits<T>::quiet_NaN();
|
||||
VERIFY_IS_EQUAL(numext::sqrt(zero), zero);
|
||||
VERIFY_IS_EQUAL(numext::sqrt(inf), inf);
|
||||
VERIFY((numext::isnan)(numext::sqrt(nan)));
|
||||
VERIFY((numext::isnan)(numext::sqrt(-one)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct check_sqrt_impl<std::complex<T> > {
|
||||
static void run() {
|
||||
typedef typename std::complex<T> ComplexT;
|
||||
|
||||
for (int i=0; i<1000; ++i) {
|
||||
const ComplexT x = internal::random<ComplexT>();
|
||||
const ComplexT sqrtx = numext::sqrt(x);
|
||||
VERIFY_IS_APPROX(sqrtx*sqrtx, x);
|
||||
}
|
||||
|
||||
// Corner cases.
|
||||
const T zero = T(0);
|
||||
const T one = T(1);
|
||||
const T inf = std::numeric_limits<T>::infinity();
|
||||
const T nan = std::numeric_limits<T>::quiet_NaN();
|
||||
|
||||
// Set of corner cases from https://en.cppreference.com/w/cpp/numeric/complex/sqrt
|
||||
const int kNumCorners = 20;
|
||||
const ComplexT corners[kNumCorners][2] = {
|
||||
{ComplexT(zero, zero), ComplexT(zero, zero)},
|
||||
{ComplexT(-zero, zero), ComplexT(zero, zero)},
|
||||
{ComplexT(zero, -zero), ComplexT(zero, zero)},
|
||||
{ComplexT(-zero, -zero), ComplexT(zero, zero)},
|
||||
{ComplexT(one, inf), ComplexT(inf, inf)},
|
||||
{ComplexT(nan, inf), ComplexT(inf, inf)},
|
||||
{ComplexT(one, -inf), ComplexT(inf, -inf)},
|
||||
{ComplexT(nan, -inf), ComplexT(inf, -inf)},
|
||||
{ComplexT(-inf, one), ComplexT(zero, inf)},
|
||||
{ComplexT(inf, one), ComplexT(inf, zero)},
|
||||
{ComplexT(-inf, -one), ComplexT(zero, -inf)},
|
||||
{ComplexT(inf, -one), ComplexT(inf, -zero)},
|
||||
{ComplexT(-inf, nan), ComplexT(nan, inf)},
|
||||
{ComplexT(inf, nan), ComplexT(inf, nan)},
|
||||
{ComplexT(zero, nan), ComplexT(nan, nan)},
|
||||
{ComplexT(one, nan), ComplexT(nan, nan)},
|
||||
{ComplexT(nan, zero), ComplexT(nan, nan)},
|
||||
{ComplexT(nan, one), ComplexT(nan, nan)},
|
||||
{ComplexT(nan, -one), ComplexT(nan, nan)},
|
||||
{ComplexT(nan, nan), ComplexT(nan, nan)},
|
||||
};
|
||||
|
||||
for (int i=0; i<kNumCorners; ++i) {
|
||||
const ComplexT& x = corners[i][0];
|
||||
const ComplexT sqrtx = corners[i][1];
|
||||
VERIFY_IS_EQUAL_OR_NANS(numext::sqrt(x), sqrtx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void check_sqrt() {
|
||||
check_sqrt_impl<T>::run();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct check_rsqrt_impl {
|
||||
static void run() {
|
||||
const T zero = T(0);
|
||||
const T one = T(1);
|
||||
const T inf = std::numeric_limits<T>::infinity();
|
||||
const T nan = std::numeric_limits<T>::quiet_NaN();
|
||||
|
||||
for (int i=0; i<1000; ++i) {
|
||||
const T x = numext::abs(internal::random<T>());
|
||||
const T rsqrtx = numext::rsqrt(x);
|
||||
const T invx = one / x;
|
||||
VERIFY_IS_APPROX(rsqrtx*rsqrtx, invx);
|
||||
}
|
||||
|
||||
// Corner cases.
|
||||
VERIFY_IS_EQUAL(numext::rsqrt(zero), inf);
|
||||
VERIFY_IS_EQUAL(numext::rsqrt(inf), zero);
|
||||
VERIFY((numext::isnan)(numext::rsqrt(nan)));
|
||||
VERIFY((numext::isnan)(numext::rsqrt(-one)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct check_rsqrt_impl<std::complex<T> > {
|
||||
static void run() {
|
||||
typedef typename std::complex<T> ComplexT;
|
||||
const T zero = T(0);
|
||||
const T one = T(1);
|
||||
const T inf = std::numeric_limits<T>::infinity();
|
||||
const T nan = std::numeric_limits<T>::quiet_NaN();
|
||||
|
||||
for (int i=0; i<1000; ++i) {
|
||||
const ComplexT x = internal::random<ComplexT>();
|
||||
const ComplexT invx = ComplexT(one, zero) / x;
|
||||
const ComplexT rsqrtx = numext::rsqrt(x);
|
||||
VERIFY_IS_APPROX(rsqrtx*rsqrtx, invx);
|
||||
}
|
||||
|
||||
// GCC and MSVC differ in their treatment of 1/(0 + 0i)
|
||||
// GCC/clang = (inf, nan)
|
||||
// MSVC = (nan, nan)
|
||||
// and 1 / (x + inf i)
|
||||
// GCC/clang = (0, 0)
|
||||
// MSVC = (nan, nan)
|
||||
#if (EIGEN_COMP_GNUC)
|
||||
{
|
||||
const int kNumCorners = 20;
|
||||
const ComplexT corners[kNumCorners][2] = {
|
||||
// Only consistent across GCC, clang
|
||||
{ComplexT(zero, zero), ComplexT(zero, zero)},
|
||||
{ComplexT(-zero, zero), ComplexT(zero, zero)},
|
||||
{ComplexT(zero, -zero), ComplexT(zero, zero)},
|
||||
{ComplexT(-zero, -zero), ComplexT(zero, zero)},
|
||||
{ComplexT(one, inf), ComplexT(inf, inf)},
|
||||
{ComplexT(nan, inf), ComplexT(inf, inf)},
|
||||
{ComplexT(one, -inf), ComplexT(inf, -inf)},
|
||||
{ComplexT(nan, -inf), ComplexT(inf, -inf)},
|
||||
// Consistent across GCC, clang, MSVC
|
||||
{ComplexT(-inf, one), ComplexT(zero, inf)},
|
||||
{ComplexT(inf, one), ComplexT(inf, zero)},
|
||||
{ComplexT(-inf, -one), ComplexT(zero, -inf)},
|
||||
{ComplexT(inf, -one), ComplexT(inf, -zero)},
|
||||
{ComplexT(-inf, nan), ComplexT(nan, inf)},
|
||||
{ComplexT(inf, nan), ComplexT(inf, nan)},
|
||||
{ComplexT(zero, nan), ComplexT(nan, nan)},
|
||||
{ComplexT(one, nan), ComplexT(nan, nan)},
|
||||
{ComplexT(nan, zero), ComplexT(nan, nan)},
|
||||
{ComplexT(nan, one), ComplexT(nan, nan)},
|
||||
{ComplexT(nan, -one), ComplexT(nan, nan)},
|
||||
{ComplexT(nan, nan), ComplexT(nan, nan)},
|
||||
};
|
||||
|
||||
for (int i=0; i<kNumCorners; ++i) {
|
||||
const ComplexT& x = corners[i][0];
|
||||
const ComplexT rsqrtx = ComplexT(one, zero) / corners[i][1];
|
||||
VERIFY_IS_EQUAL_OR_NANS(numext::rsqrt(x), rsqrtx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void check_rsqrt() {
|
||||
check_rsqrt_impl<T>::run();
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(numext) {
|
||||
for(int k=0; k<g_repeat; ++k)
|
||||
{
|
||||
CALL_SUBTEST( check_abs<bool>() );
|
||||
CALL_SUBTEST( check_abs<signed char>() );
|
||||
CALL_SUBTEST( check_abs<unsigned char>() );
|
||||
CALL_SUBTEST( check_abs<short>() );
|
||||
CALL_SUBTEST( check_abs<unsigned short>() );
|
||||
CALL_SUBTEST( check_abs<int>() );
|
||||
CALL_SUBTEST( check_abs<unsigned int>() );
|
||||
CALL_SUBTEST( check_abs<long>() );
|
||||
CALL_SUBTEST( check_abs<unsigned long>() );
|
||||
CALL_SUBTEST( check_abs<half>() );
|
||||
CALL_SUBTEST( check_abs<bfloat16>() );
|
||||
CALL_SUBTEST( check_abs<float>() );
|
||||
CALL_SUBTEST( check_abs<double>() );
|
||||
CALL_SUBTEST( check_abs<long double>() );
|
||||
CALL_SUBTEST( check_abs<std::complex<float> >() );
|
||||
CALL_SUBTEST( check_abs<std::complex<double> >() );
|
||||
|
||||
CALL_SUBTEST( check_arg<std::complex<float> >() );
|
||||
CALL_SUBTEST( check_arg<std::complex<double> >() );
|
||||
|
||||
CALL_SUBTEST( check_sqrt<float>() );
|
||||
CALL_SUBTEST( check_sqrt<double>() );
|
||||
CALL_SUBTEST( check_sqrt<std::complex<float> >() );
|
||||
CALL_SUBTEST( check_sqrt<std::complex<double> >() );
|
||||
|
||||
CALL_SUBTEST( check_rsqrt<float>() );
|
||||
CALL_SUBTEST( check_rsqrt<double>() );
|
||||
CALL_SUBTEST( check_rsqrt<std::complex<float> >() );
|
||||
CALL_SUBTEST( check_rsqrt<std::complex<double> >() );
|
||||
}
|
||||
}
|
||||
1302
libs/eigen/test/packetmath.cpp
Normal file
1302
libs/eigen/test/packetmath.cpp
Normal file
File diff suppressed because it is too large
Load Diff
275
libs/eigen/test/packetmath_test_shared.h
Normal file
275
libs/eigen/test/packetmath_test_shared.h
Normal file
@@ -0,0 +1,275 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 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/.
|
||||
|
||||
#include "main.h"
|
||||
#include <typeinfo>
|
||||
|
||||
#if defined __GNUC__ && __GNUC__>=6
|
||||
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||
#endif
|
||||
// using namespace Eigen;
|
||||
|
||||
bool g_first_pass = true;
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
template<typename T> T negate(const T& x) { return -x; }
|
||||
|
||||
template<typename T>
|
||||
Map<const Array<unsigned char,sizeof(T),1> >
|
||||
bits(const T& x) {
|
||||
return Map<const Array<unsigned char,sizeof(T),1> >(reinterpret_cast<const unsigned char *>(&x));
|
||||
}
|
||||
|
||||
// The following implement bitwise operations on floating point types
|
||||
template<typename T,typename Bits,typename Func>
|
||||
T apply_bit_op(Bits a, Bits b, Func f) {
|
||||
Array<unsigned char,sizeof(T),1> data;
|
||||
T res;
|
||||
for(Index i = 0; i < data.size(); ++i)
|
||||
data[i] = f(a[i], b[i]);
|
||||
// Note: The reinterpret_cast works around GCC's class-memaccess warnings:
|
||||
std::memcpy(reinterpret_cast<unsigned char*>(&res), data.data(), sizeof(T));
|
||||
return res;
|
||||
}
|
||||
|
||||
#define EIGEN_TEST_MAKE_BITWISE2(OP,FUNC,T) \
|
||||
template<> T EIGEN_CAT(p,OP)(const T& a,const T& b) { \
|
||||
return apply_bit_op<T>(bits(a),bits(b),FUNC); \
|
||||
}
|
||||
|
||||
#define EIGEN_TEST_MAKE_BITWISE(OP,FUNC) \
|
||||
EIGEN_TEST_MAKE_BITWISE2(OP,FUNC,float) \
|
||||
EIGEN_TEST_MAKE_BITWISE2(OP,FUNC,double) \
|
||||
EIGEN_TEST_MAKE_BITWISE2(OP,FUNC,half) \
|
||||
EIGEN_TEST_MAKE_BITWISE2(OP,FUNC,bfloat16) \
|
||||
EIGEN_TEST_MAKE_BITWISE2(OP,FUNC,std::complex<float>) \
|
||||
EIGEN_TEST_MAKE_BITWISE2(OP,FUNC,std::complex<double>)
|
||||
|
||||
EIGEN_TEST_MAKE_BITWISE(xor,std::bit_xor<unsigned char>())
|
||||
EIGEN_TEST_MAKE_BITWISE(and,std::bit_and<unsigned char>())
|
||||
EIGEN_TEST_MAKE_BITWISE(or, std::bit_or<unsigned char>())
|
||||
struct bit_andnot{
|
||||
template<typename T> T
|
||||
operator()(T a, T b) const { return a & (~b); }
|
||||
};
|
||||
EIGEN_TEST_MAKE_BITWISE(andnot, bit_andnot())
|
||||
template<typename T>
|
||||
bool biteq(T a, T b) {
|
||||
return (bits(a) == bits(b)).all();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace test {
|
||||
|
||||
// NOTE: we disable 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);
|
||||
}
|
||||
|
||||
template<typename Scalar>
|
||||
inline void print_mismatch(const Scalar* ref, const Scalar* vec, int size) {
|
||||
std::cout << "ref: [" << Map<const Matrix<Scalar,1,Dynamic> >(ref,size) << "]" << " != vec: [" << Map<const Matrix<Scalar,1,Dynamic> >(vec,size) << "]\n";
|
||||
}
|
||||
|
||||
template<typename Scalar> bool areApproxAbs(const Scalar* a, const Scalar* b, int size, const typename NumTraits<Scalar>::Real& refvalue)
|
||||
{
|
||||
for (int i=0; i<size; ++i)
|
||||
{
|
||||
if (!isApproxAbs(a[i],b[i],refvalue))
|
||||
{
|
||||
print_mismatch(a, b, size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Scalar> bool areApprox(const Scalar* a, const Scalar* b, int size)
|
||||
{
|
||||
for (int i=0; i<size; ++i)
|
||||
{
|
||||
if ( a[i]!=b[i] && !internal::isApprox(a[i],b[i])
|
||||
&& !((numext::isnan)(a[i]) && (numext::isnan)(b[i])) )
|
||||
{
|
||||
print_mismatch(a, b, size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Scalar> bool areEqual(const Scalar* a, const Scalar* b, int size)
|
||||
{
|
||||
for (int i=0; i<size; ++i)
|
||||
{
|
||||
if ( (a[i] != b[i]) && !((numext::isnan)(a[i]) && (numext::isnan)(b[i])) )
|
||||
{
|
||||
print_mismatch(a, b, size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CHECK_CWISE1(REFOP, POP) { \
|
||||
for (int i=0; i<PacketSize; ++i) \
|
||||
ref[i] = REFOP(data1[i]); \
|
||||
internal::pstore(data2, POP(internal::pload<Packet>(data1))); \
|
||||
VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
// Checks component-wise for input of size N. All of data1, data2, and ref
|
||||
// should have size at least ceil(N/PacketSize)*PacketSize to avoid memory
|
||||
// access errors.
|
||||
#define CHECK_CWISE1_N(REFOP, POP, N) { \
|
||||
for (int i=0; i<N; ++i) \
|
||||
ref[i] = REFOP(data1[i]); \
|
||||
for (int j=0; j<N; j+=PacketSize) \
|
||||
internal::pstore(data2 + j, POP(internal::pload<Packet>(data1 + j))); \
|
||||
VERIFY(test::areApprox(ref, data2, N) && #POP); \
|
||||
}
|
||||
|
||||
template<bool Cond,typename Packet>
|
||||
struct packet_helper
|
||||
{
|
||||
template<typename T>
|
||||
inline Packet load(const T* from) const { return internal::pload<Packet>(from); }
|
||||
|
||||
template<typename T>
|
||||
inline Packet loadu(const T* from) const { return internal::ploadu<Packet>(from); }
|
||||
|
||||
template<typename T>
|
||||
inline Packet load(const T* from, unsigned long long umask) const { return internal::ploadu<Packet>(from, umask); }
|
||||
|
||||
template<typename T>
|
||||
inline void store(T* to, const Packet& x) const { internal::pstore(to,x); }
|
||||
|
||||
template<typename T>
|
||||
inline void store(T* to, const Packet& x, unsigned long long umask) const { internal::pstoreu(to, x, umask); }
|
||||
|
||||
template<typename T>
|
||||
inline Packet& forward_reference(Packet& packet, T& /*scalar*/) const { return packet; }
|
||||
};
|
||||
|
||||
template<typename Packet>
|
||||
struct packet_helper<false,Packet>
|
||||
{
|
||||
template<typename T>
|
||||
inline T load(const T* from) const { return *from; }
|
||||
|
||||
template<typename T>
|
||||
inline T loadu(const T* from) const { return *from; }
|
||||
|
||||
template<typename T>
|
||||
inline T load(const T* from, unsigned long long) const { return *from; }
|
||||
|
||||
template<typename T>
|
||||
inline void store(T* to, const T& x) const { *to = x; }
|
||||
|
||||
template<typename T>
|
||||
inline void store(T* to, const T& x, unsigned long long) const { *to = x; }
|
||||
|
||||
template<typename T>
|
||||
inline T& forward_reference(Packet& /*packet*/, T& scalar) const { return scalar; }
|
||||
};
|
||||
|
||||
#define CHECK_CWISE1_IF(COND, REFOP, POP) if(COND) { \
|
||||
test::packet_helper<COND,Packet> h; \
|
||||
for (int i=0; i<PacketSize; ++i) \
|
||||
ref[i] = Scalar(REFOP(data1[i])); \
|
||||
h.store(data2, POP(h.load(data1))); \
|
||||
VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
#define CHECK_CWISE1_EXACT_IF(COND, REFOP, POP) if(COND) { \
|
||||
test::packet_helper<COND,Packet> h; \
|
||||
for (int i=0; i<PacketSize; ++i) \
|
||||
ref[i] = Scalar(REFOP(data1[i])); \
|
||||
h.store(data2, POP(h.load(data1))); \
|
||||
VERIFY(test::areEqual(ref, data2, PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
#define CHECK_CWISE2_IF(COND, REFOP, POP) if(COND) { \
|
||||
test::packet_helper<COND,Packet> h; \
|
||||
for (int i=0; i<PacketSize; ++i) \
|
||||
ref[i] = Scalar(REFOP(data1[i], data1[i+PacketSize])); \
|
||||
h.store(data2, POP(h.load(data1),h.load(data1+PacketSize))); \
|
||||
VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
// One input, one output by reference.
|
||||
#define CHECK_CWISE1_BYREF1_IF(COND, REFOP, POP) if(COND) { \
|
||||
test::packet_helper<COND,Packet> h; \
|
||||
for (int i=0; i<PacketSize; ++i) \
|
||||
ref[i] = Scalar(REFOP(data1[i], ref[i+PacketSize])); \
|
||||
Packet pout; \
|
||||
Scalar sout; \
|
||||
h.store(data2, POP(h.load(data1), h.forward_reference(pout, sout))); \
|
||||
h.store(data2+PacketSize, h.forward_reference(pout, sout)); \
|
||||
VERIFY(test::areApprox(ref, data2, 2 * PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
#define CHECK_CWISE3_IF(COND, REFOP, POP) if (COND) { \
|
||||
test::packet_helper<COND, Packet> h; \
|
||||
for (int i = 0; i < PacketSize; ++i) \
|
||||
ref[i] = Scalar(REFOP(data1[i], data1[i + PacketSize], \
|
||||
data1[i + 2 * PacketSize])); \
|
||||
h.store(data2, POP(h.load(data1), h.load(data1 + PacketSize), \
|
||||
h.load(data1 + 2 * PacketSize))); \
|
||||
VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
// Specialize the runall struct in your test file by defining run().
|
||||
template<
|
||||
typename Scalar,
|
||||
typename PacketType,
|
||||
bool IsComplex = NumTraits<Scalar>::IsComplex,
|
||||
bool IsInteger = NumTraits<Scalar>::IsInteger>
|
||||
struct runall;
|
||||
|
||||
template<
|
||||
typename Scalar,
|
||||
typename PacketType = typename internal::packet_traits<Scalar>::type,
|
||||
bool Vectorized = internal::packet_traits<Scalar>::Vectorizable,
|
||||
bool HasHalf = !internal::is_same<typename internal::unpacket_traits<PacketType>::half,PacketType>::value >
|
||||
struct runner;
|
||||
|
||||
template<typename Scalar,typename PacketType>
|
||||
struct runner<Scalar,PacketType,true,true>
|
||||
{
|
||||
static void run() {
|
||||
runall<Scalar,PacketType>::run();
|
||||
runner<Scalar,typename internal::unpacket_traits<PacketType>::half>::run();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar,typename PacketType>
|
||||
struct runner<Scalar,PacketType,true,false>
|
||||
{
|
||||
static void run() {
|
||||
runall<Scalar,PacketType>::run();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar,typename PacketType>
|
||||
struct runner<Scalar,PacketType,false,false>
|
||||
{
|
||||
static void run() {
|
||||
runall<Scalar,PacketType>::run();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
29
libs/eigen/test/pardiso_support.cpp
Normal file
29
libs/eigen/test/pardiso_support.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Intel Copyright (C) ....
|
||||
*/
|
||||
|
||||
#include "sparse_solver.h"
|
||||
#include <Eigen/PardisoSupport>
|
||||
|
||||
template<typename T> void test_pardiso_T()
|
||||
{
|
||||
PardisoLLT < SparseMatrix<T, RowMajor>, Lower> pardiso_llt_lower;
|
||||
PardisoLLT < SparseMatrix<T, RowMajor>, Upper> pardiso_llt_upper;
|
||||
PardisoLDLT < SparseMatrix<T, RowMajor>, Lower> pardiso_ldlt_lower;
|
||||
PardisoLDLT < SparseMatrix<T, RowMajor>, Upper> pardiso_ldlt_upper;
|
||||
PardisoLU < SparseMatrix<T, RowMajor> > pardiso_lu;
|
||||
|
||||
check_sparse_spd_solving(pardiso_llt_lower);
|
||||
check_sparse_spd_solving(pardiso_llt_upper);
|
||||
check_sparse_spd_solving(pardiso_ldlt_lower);
|
||||
check_sparse_spd_solving(pardiso_ldlt_upper);
|
||||
check_sparse_square_solving(pardiso_lu);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(pardiso_support)
|
||||
{
|
||||
CALL_SUBTEST_1(test_pardiso_T<float>());
|
||||
CALL_SUBTEST_2(test_pardiso_T<double>());
|
||||
CALL_SUBTEST_3(test_pardiso_T< std::complex<float> >());
|
||||
CALL_SUBTEST_4(test_pardiso_T< std::complex<double> >());
|
||||
}
|
||||
54
libs/eigen/test/pastix_support.cpp
Normal file
54
libs/eigen/test/pastix_support.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@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_NO_DEBUG_SMALL_PRODUCT_BLOCKS
|
||||
#include "sparse_solver.h"
|
||||
#include <Eigen/PaStiXSupport>
|
||||
#include <unsupported/Eigen/SparseExtra>
|
||||
|
||||
|
||||
template<typename T> void test_pastix_T()
|
||||
{
|
||||
PastixLLT< SparseMatrix<T, ColMajor>, Eigen::Lower > pastix_llt_lower;
|
||||
PastixLDLT< SparseMatrix<T, ColMajor>, Eigen::Lower > pastix_ldlt_lower;
|
||||
PastixLLT< SparseMatrix<T, ColMajor>, Eigen::Upper > pastix_llt_upper;
|
||||
PastixLDLT< SparseMatrix<T, ColMajor>, Eigen::Upper > pastix_ldlt_upper;
|
||||
PastixLU< SparseMatrix<T, ColMajor> > pastix_lu;
|
||||
|
||||
check_sparse_spd_solving(pastix_llt_lower);
|
||||
check_sparse_spd_solving(pastix_ldlt_lower);
|
||||
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.
|
||||
// Complex symmetric matrices should pass though
|
||||
template<typename T> void test_pastix_T_LU()
|
||||
{
|
||||
PastixLU< SparseMatrix<T, ColMajor> > pastix_lu;
|
||||
check_sparse_square_solving(pastix_lu);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(pastix_support)
|
||||
{
|
||||
CALL_SUBTEST_1(test_pastix_T<float>());
|
||||
CALL_SUBTEST_2(test_pastix_T<double>());
|
||||
CALL_SUBTEST_3( (test_pastix_T_LU<std::complex<float> >()) );
|
||||
CALL_SUBTEST_4(test_pastix_T_LU<std::complex<double> >());
|
||||
}
|
||||
181
libs/eigen/test/permutationmatrices.cpp
Normal file
181
libs/eigen/test/permutationmatrices.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
// 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 TEST_ENABLE_TEMPORARY_TRACKING
|
||||
|
||||
#include "main.h"
|
||||
|
||||
using namespace std;
|
||||
template<typename MatrixType> void permutationmatrices(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime,
|
||||
Options = MatrixType::Options };
|
||||
typedef PermutationMatrix<Rows> LeftPermutationType;
|
||||
typedef Transpositions<Rows> LeftTranspositionsType;
|
||||
typedef Matrix<int, Rows, 1> LeftPermutationVectorType;
|
||||
typedef Map<LeftPermutationType> MapLeftPerm;
|
||||
typedef PermutationMatrix<Cols> RightPermutationType;
|
||||
typedef Transpositions<Cols> RightTranspositionsType;
|
||||
typedef Matrix<int, Cols, 1> RightPermutationVectorType;
|
||||
typedef Map<RightPermutationType> MapRightPerm;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m_original = MatrixType::Random(rows,cols);
|
||||
LeftPermutationVectorType lv;
|
||||
randomPermutationVector(lv, rows);
|
||||
LeftPermutationType lp(lv);
|
||||
RightPermutationVectorType rv;
|
||||
randomPermutationVector(rv, cols);
|
||||
RightPermutationType rp(rv);
|
||||
LeftTranspositionsType lt(lv);
|
||||
RightTranspositionsType rt(rv);
|
||||
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++)
|
||||
VERIFY_IS_APPROX(m_permuted(lv(i),j), m_original(i,rv(j)));
|
||||
|
||||
Matrix<Scalar,Rows,Rows> lm(lp);
|
||||
Matrix<Scalar,Cols,Cols> rm(rp);
|
||||
|
||||
VERIFY_IS_APPROX(m_permuted, lm*m_original*rm);
|
||||
|
||||
m_permuted = m_original;
|
||||
VERIFY_EVALUATION_COUNT(m_permuted = lp * m_permuted * rp, 1);
|
||||
VERIFY_IS_APPROX(m_permuted, lm*m_original*rm);
|
||||
|
||||
LeftPermutationType lpi;
|
||||
lpi = lp.inverse();
|
||||
VERIFY_IS_APPROX(lpi*m_permuted,lp.inverse()*m_permuted);
|
||||
|
||||
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);
|
||||
|
||||
VERIFY((lp*lp.inverse()).toDenseMatrix().isIdentity());
|
||||
VERIFY((lv.asPermutation()*lv.asPermutation().inverse()).toDenseMatrix().isIdentity());
|
||||
VERIFY((MapLeftPerm(lv.data(),lv.size())*MapLeftPerm(lv.data(),lv.size()).inverse()).toDenseMatrix().isIdentity());
|
||||
|
||||
LeftPermutationVectorType lv2;
|
||||
randomPermutationVector(lv2, rows);
|
||||
LeftPermutationType lp2(lv2);
|
||||
Matrix<Scalar,Rows,Rows> lm2(lp2);
|
||||
VERIFY_IS_APPROX((lp*lp2).toDenseMatrix().template cast<Scalar>(), lm*lm2);
|
||||
VERIFY_IS_APPROX((lv.asPermutation()*lv2.asPermutation()).toDenseMatrix().template cast<Scalar>(), lm*lm2);
|
||||
VERIFY_IS_APPROX((MapLeftPerm(lv.data(),lv.size())*MapLeftPerm(lv2.data(),lv2.size())).toDenseMatrix().template cast<Scalar>(), lm*lm2);
|
||||
|
||||
LeftPermutationType identityp;
|
||||
identityp.setIdentity(rows);
|
||||
VERIFY_IS_APPROX(m_original, identityp*m_original);
|
||||
|
||||
// check inplace permutations
|
||||
m_permuted = m_original;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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)
|
||||
{
|
||||
lp2 = lp;
|
||||
Index i = internal::random<Index>(0, rows-1);
|
||||
Index j;
|
||||
do j = internal::random<Index>(0, rows-1); while(j==i);
|
||||
lp2.applyTranspositionOnTheLeft(i, j);
|
||||
lm = lp;
|
||||
lm.row(i).swap(lm.row(j));
|
||||
VERIFY_IS_APPROX(lm, lp2.toDenseMatrix().template cast<Scalar>());
|
||||
|
||||
RightPermutationType rp2 = rp;
|
||||
i = internal::random<Index>(0, cols-1);
|
||||
do j = internal::random<Index>(0, cols-1); while(j==i);
|
||||
rp2.applyTranspositionOnTheRight(i, j);
|
||||
rm = rp;
|
||||
rm.col(i).swap(rm.col(j));
|
||||
VERIFY_IS_APPROX(rm, rp2.toDenseMatrix().template cast<Scalar>());
|
||||
}
|
||||
|
||||
{
|
||||
// simple compilation check
|
||||
Matrix<Scalar, Cols, Cols> A = rp;
|
||||
Matrix<Scalar, Cols, Cols> B = rp.transpose();
|
||||
VERIFY_IS_APPROX(A, B.transpose());
|
||||
}
|
||||
|
||||
m_permuted = m_original;
|
||||
lp = lt;
|
||||
rp = rt;
|
||||
VERIFY_EVALUATION_COUNT(m_permuted = lt * m_permuted * rt, 1);
|
||||
VERIFY_IS_APPROX(m_permuted, lp*m_original*rp.transpose());
|
||||
|
||||
VERIFY_IS_APPROX(lt.inverse()*m_permuted*rt.inverse(), m_original);
|
||||
|
||||
// Check inplace transpositions
|
||||
m_permuted = m_original;
|
||||
VERIFY_IS_APPROX(m_permuted = lt * m_permuted, lp * m_original);
|
||||
m_permuted = m_original;
|
||||
VERIFY_IS_APPROX(m_permuted = lt.inverse() * m_permuted, lp.inverse() * m_original);
|
||||
m_permuted = m_original;
|
||||
VERIFY_IS_APPROX(m_permuted = m_permuted * rt, m_original * rt);
|
||||
m_permuted = m_original;
|
||||
VERIFY_IS_APPROX(m_permuted = m_permuted * rt.inverse(), m_original * rt.inverse());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(permutationmatrices)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( permutationmatrices(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( permutationmatrices(Matrix3f()) );
|
||||
CALL_SUBTEST_3( permutationmatrices(Matrix<double,3,3,RowMajor>()) );
|
||||
CALL_SUBTEST_4( permutationmatrices(Matrix4d()) );
|
||||
CALL_SUBTEST_5( permutationmatrices(Matrix<double,40,60>()) );
|
||||
CALL_SUBTEST_6( permutationmatrices(Matrix<double,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_7( permutationmatrices(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
CALL_SUBTEST_5( bug890<double>() );
|
||||
}
|
||||
82
libs/eigen/test/prec_inverse_4x4.cpp
Normal file
82
libs/eigen/test/prec_inverse_4x4.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// 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 MatrixType> void inverse_permutation_4x4()
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
Vector4i indices(0,1,2,3);
|
||||
for(int i = 0; i < 24; ++i)
|
||||
{
|
||||
MatrixType m = PermutationMatrix<4>(indices);
|
||||
MatrixType inv = m.inverse();
|
||||
double error = double( (m*inv-MatrixType::Identity()).norm() / NumTraits<Scalar>::epsilon() );
|
||||
EIGEN_DEBUG_VAR(error)
|
||||
VERIFY(error == 0.0);
|
||||
std::next_permutation(indices.data(),indices.data()+4);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType> void inverse_general_4x4(int repeat)
|
||||
{
|
||||
using std::abs;
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
double error_sum = 0., error_max = 0.;
|
||||
for(int i = 0; i < repeat; ++i)
|
||||
{
|
||||
MatrixType m;
|
||||
bool is_invertible;
|
||||
do {
|
||||
m = MatrixType::Random();
|
||||
is_invertible = Eigen::FullPivLU<MatrixType>(m).isInvertible();
|
||||
} while(!is_invertible);
|
||||
MatrixType inv = m.inverse();
|
||||
double error = double( (m*inv-MatrixType::Identity()).norm());
|
||||
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);
|
||||
// FIXME that 1.25 used to be a 1.0 until the NumTraits changes on 28 April 2010, what's going wrong??
|
||||
// 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)));
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_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>()));
|
||||
CALL_SUBTEST_3((inverse_general_4x4<Matrix4cf>(50000 * g_repeat)));
|
||||
}
|
||||
259
libs/eigen/test/product.h
Normal file
259
libs/eigen/test/product.h
Normal file
@@ -0,0 +1,259 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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/QR>
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
bool areNotApprox(const MatrixBase<Derived1>& m1, const MatrixBase<Derived2>& m2, typename Derived1::RealScalar epsilon = NumTraits<typename Derived1::RealScalar>::dummy_precision())
|
||||
{
|
||||
return !((m1-m2).cwiseAbs2().maxCoeff() < epsilon * epsilon
|
||||
* (std::max)(m1.cwiseAbs2().maxCoeff(), m2.cwiseAbs2().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 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::Flags&RowMajorBit?ColMajor:RowMajor> OtherMajorMatrixType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index 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 = internal::random<Scalar>();
|
||||
|
||||
Index r = internal::random<Index>(0, rows-1),
|
||||
c = internal::random<Index>(0, cols-1),
|
||||
c2 = internal::random<Index>(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 * (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));
|
||||
|
||||
// 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>::IsInteger && (std::min)(rows,cols)>1)
|
||||
{
|
||||
VERIFY(areNotApprox(m1.transpose()*m2,m2.transpose()*m1));
|
||||
}
|
||||
|
||||
// test optimized operator+= path
|
||||
res = square;
|
||||
res.noalias() += m1 * m2.transpose();
|
||||
VERIFY_IS_APPROX(res, square + m1 * m2.transpose());
|
||||
if (!NumTraits<Scalar>::IsInteger && (std::min)(rows,cols)>1)
|
||||
{
|
||||
VERIFY(areNotApprox(res,square + m2 * m1.transpose()));
|
||||
}
|
||||
vcres = vc2;
|
||||
vcres.noalias() += m1.transpose() * v1;
|
||||
VERIFY_IS_APPROX(vcres, vc2 + m1.transpose() * v1);
|
||||
|
||||
// test optimized operator-= path
|
||||
res = square;
|
||||
res.noalias() -= m1 * m2.transpose();
|
||||
VERIFY_IS_APPROX(res, square - (m1 * m2.transpose()));
|
||||
if (!NumTraits<Scalar>::IsInteger && (std::min)(rows,cols)>1)
|
||||
{
|
||||
VERIFY(areNotApprox(res,square - m2 * m1.transpose()));
|
||||
}
|
||||
vcres = vc2;
|
||||
vcres.noalias() -= m1.transpose() * v1;
|
||||
VERIFY_IS_APPROX(vcres, vc2 - m1.transpose() * v1);
|
||||
|
||||
// test scaled products
|
||||
res = square;
|
||||
res.noalias() = s1 * m1 * m2.transpose();
|
||||
VERIFY_IS_APPROX(res, ((s1*m1).eval() * m2.transpose()));
|
||||
res = square;
|
||||
res.noalias() += s1 * m1 * m2.transpose();
|
||||
VERIFY_IS_APPROX(res, square + ((s1*m1).eval() * m2.transpose()));
|
||||
res = square;
|
||||
res.noalias() -= s1 * m1 * m2.transpose();
|
||||
VERIFY_IS_APPROX(res, square - ((s1*m1).eval() * 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());
|
||||
|
||||
// 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);
|
||||
|
||||
// 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.noalias() += m1.transpose() * m2;
|
||||
VERIFY_IS_APPROX(res2, square2 + m1.transpose() * m2);
|
||||
if (!NumTraits<Scalar>::IsInteger && (std::min)(rows,cols)>1)
|
||||
{
|
||||
VERIFY(areNotApprox(res2,square2 + m2.transpose() * m1));
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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;
|
||||
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());
|
||||
}
|
||||
|
||||
// destination with a non-default inner-stride
|
||||
// see bug 1741
|
||||
if(!MatrixType::IsRowMajor)
|
||||
{
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic> MatrixX;
|
||||
MatrixX buffer(2*rows,2*rows);
|
||||
Map<RowSquareMatrixType,0,Stride<Dynamic,2> > map1(buffer.data(),rows,rows,Stride<Dynamic,2>(2*rows,2));
|
||||
buffer.setZero();
|
||||
VERIFY_IS_APPROX(map1 = m1 * m2.transpose(), (m1 * m2.transpose()).eval());
|
||||
buffer.setZero();
|
||||
VERIFY_IS_APPROX(map1.noalias() = m1 * m2.transpose(), (m1 * m2.transpose()).eval());
|
||||
buffer.setZero();
|
||||
VERIFY_IS_APPROX(map1.noalias() += m1 * m2.transpose(), (m1 * m2.transpose()).eval());
|
||||
}
|
||||
|
||||
}
|
||||
390
libs/eigen/test/product_extra.cpp
Normal file
390
libs/eigen/test/product_extra.cpp
Normal file
@@ -0,0 +1,390 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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 product_extra(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
|
||||
typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic,
|
||||
MatrixType::Flags&RowMajorBit> OtherMajorMatrixType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
identity = MatrixType::Identity(rows, rows),
|
||||
square = MatrixType::Random(rows, rows),
|
||||
res = MatrixType::Random(rows, rows),
|
||||
square2 = MatrixType::Random(cols, cols),
|
||||
res2 = MatrixType::Random(cols, cols);
|
||||
RowVectorType v1 = RowVectorType::Random(rows), vrres(rows);
|
||||
ColVectorType vc2 = ColVectorType::Random(cols), vcres(cols);
|
||||
OtherMajorMatrixType tm1 = m1;
|
||||
|
||||
Scalar s1 = internal::random<Scalar>(),
|
||||
s2 = internal::random<Scalar>(),
|
||||
s3 = internal::random<Scalar>();
|
||||
|
||||
VERIFY_IS_APPROX(m3.noalias() = m1 * m2.adjoint(), m1 * m2.adjoint().eval());
|
||||
VERIFY_IS_APPROX(m3.noalias() = m1.adjoint() * square.adjoint(), m1.adjoint().eval() * square.adjoint().eval());
|
||||
VERIFY_IS_APPROX(m3.noalias() = m1.adjoint() * m2, m1.adjoint().eval() * m2);
|
||||
VERIFY_IS_APPROX(m3.noalias() = (s1 * m1.adjoint()) * m2, (s1 * m1.adjoint()).eval() * m2);
|
||||
VERIFY_IS_APPROX(m3.noalias() = ((s1 * m1).adjoint()) * m2, (numext::conj(s1) * m1.adjoint()).eval() * m2);
|
||||
VERIFY_IS_APPROX(m3.noalias() = (- m1.adjoint() * s1) * (s3 * m2), (- m1.adjoint() * s1).eval() * (s3 * m2).eval());
|
||||
VERIFY_IS_APPROX(m3.noalias() = (s2 * m1.adjoint() * s1) * m2, (s2 * m1.adjoint() * s1).eval() * m2);
|
||||
VERIFY_IS_APPROX(m3.noalias() = (-m1*s2) * s1*m2.adjoint(), (-m1*s2).eval() * (s1*m2.adjoint()).eval());
|
||||
|
||||
// a very tricky case where a scale factor has to be automatically conjugated:
|
||||
VERIFY_IS_APPROX( m1.adjoint() * (s1*m2).conjugate(), (m1.adjoint()).eval() * ((s1*m2).conjugate()).eval());
|
||||
|
||||
|
||||
// test all possible conjugate combinations for the four matrix-vector product cases:
|
||||
|
||||
VERIFY_IS_APPROX((-m1.conjugate() * s2) * (s1 * vc2),
|
||||
(-m1.conjugate()*s2).eval() * (s1 * vc2).eval());
|
||||
VERIFY_IS_APPROX((-m1 * s2) * (s1 * vc2.conjugate()),
|
||||
(-m1*s2).eval() * (s1 * vc2.conjugate()).eval());
|
||||
VERIFY_IS_APPROX((-m1.conjugate() * s2) * (s1 * vc2.conjugate()),
|
||||
(-m1.conjugate()*s2).eval() * (s1 * vc2.conjugate()).eval());
|
||||
|
||||
VERIFY_IS_APPROX((s1 * vc2.transpose()) * (-m1.adjoint() * s2),
|
||||
(s1 * vc2.transpose()).eval() * (-m1.adjoint()*s2).eval());
|
||||
VERIFY_IS_APPROX((s1 * vc2.adjoint()) * (-m1.transpose() * s2),
|
||||
(s1 * vc2.adjoint()).eval() * (-m1.transpose()*s2).eval());
|
||||
VERIFY_IS_APPROX((s1 * vc2.adjoint()) * (-m1.adjoint() * s2),
|
||||
(s1 * vc2.adjoint()).eval() * (-m1.adjoint()*s2).eval());
|
||||
|
||||
VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.transpose()),
|
||||
(-m1.adjoint()*s2).eval() * (s1 * v1.transpose()).eval());
|
||||
VERIFY_IS_APPROX((-m1.transpose() * s2) * (s1 * v1.adjoint()),
|
||||
(-m1.transpose()*s2).eval() * (s1 * v1.adjoint()).eval());
|
||||
VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.adjoint()),
|
||||
(-m1.adjoint()*s2).eval() * (s1 * v1.adjoint()).eval());
|
||||
|
||||
VERIFY_IS_APPROX((s1 * v1) * (-m1.conjugate() * s2),
|
||||
(s1 * v1).eval() * (-m1.conjugate()*s2).eval());
|
||||
VERIFY_IS_APPROX((s1 * v1.conjugate()) * (-m1 * s2),
|
||||
(s1 * v1.conjugate()).eval() * (-m1*s2).eval());
|
||||
VERIFY_IS_APPROX((s1 * v1.conjugate()) * (-m1.conjugate() * s2),
|
||||
(s1 * v1.conjugate()).eval() * (-m1.conjugate()*s2).eval());
|
||||
|
||||
VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.adjoint()),
|
||||
(-m1.adjoint()*s2).eval() * (s1 * v1.adjoint()).eval());
|
||||
|
||||
// test the vector-matrix product with non aligned starts
|
||||
Index i = internal::random<Index>(0,m1.rows()-2);
|
||||
Index j = internal::random<Index>(0,m1.cols()-2);
|
||||
Index r = internal::random<Index>(1,m1.rows()-i);
|
||||
Index c = internal::random<Index>(1,m1.cols()-j);
|
||||
Index i2 = internal::random<Index>(0,m1.rows()-1);
|
||||
Index j2 = internal::random<Index>(0,m1.cols()-1);
|
||||
|
||||
VERIFY_IS_APPROX(m1.col(j2).adjoint() * m1.block(0,j,m1.rows(),c), m1.col(j2).adjoint().eval() * m1.block(0,j,m1.rows(),c).eval());
|
||||
VERIFY_IS_APPROX(m1.block(i,0,r,m1.cols()) * m1.row(i2).adjoint(), m1.block(i,0,r,m1.cols()).eval() * m1.row(i2).adjoint().eval());
|
||||
|
||||
// test negative strides
|
||||
{
|
||||
Map<MatrixType,Unaligned,Stride<Dynamic,Dynamic> > map1(&m1(rows-1,cols-1), rows, cols, Stride<Dynamic,Dynamic>(-m1.outerStride(),-1));
|
||||
Map<MatrixType,Unaligned,Stride<Dynamic,Dynamic> > map2(&m2(rows-1,cols-1), rows, cols, Stride<Dynamic,Dynamic>(-m2.outerStride(),-1));
|
||||
Map<RowVectorType,Unaligned,InnerStride<-1> > mapv1(&v1(v1.size()-1), v1.size(), InnerStride<-1>(-1));
|
||||
Map<ColVectorType,Unaligned,InnerStride<-1> > mapvc2(&vc2(vc2.size()-1), vc2.size(), InnerStride<-1>(-1));
|
||||
VERIFY_IS_APPROX(MatrixType(map1), m1.reverse());
|
||||
VERIFY_IS_APPROX(MatrixType(map2), m2.reverse());
|
||||
VERIFY_IS_APPROX(m3.noalias() = MatrixType(map1) * MatrixType(map2).adjoint(), m1.reverse() * m2.reverse().adjoint());
|
||||
VERIFY_IS_APPROX(m3.noalias() = map1 * map2.adjoint(), m1.reverse() * m2.reverse().adjoint());
|
||||
VERIFY_IS_APPROX(map1 * vc2, m1.reverse() * vc2);
|
||||
VERIFY_IS_APPROX(m1 * mapvc2, m1 * mapvc2);
|
||||
VERIFY_IS_APPROX(map1.adjoint() * v1.transpose(), m1.adjoint().reverse() * v1.transpose());
|
||||
VERIFY_IS_APPROX(m1.adjoint() * mapv1.transpose(), m1.adjoint() * v1.reverse().transpose());
|
||||
}
|
||||
|
||||
// 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
|
||||
void mat_mat_scalar_scalar_product()
|
||||
{
|
||||
Eigen::Matrix2Xd dNdxy(2, 3);
|
||||
dNdxy << -0.5, 0.5, 0,
|
||||
-0.3, 0, 0.3;
|
||||
double det = 6.0, wt = 0.5;
|
||||
VERIFY_IS_APPROX(dNdxy.transpose()*dNdxy*det*wt, det*wt*dNdxy.transpose()*dNdxy);
|
||||
}
|
||||
|
||||
template <typename MatrixType>
|
||||
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;
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
{
|
||||
MatrixType res, a(rows,0), b(0,cols);
|
||||
VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(rows,cols) );
|
||||
VERIFY_IS_APPROX( (res=a*a.transpose()), MatrixType::Zero(rows,rows) );
|
||||
VERIFY_IS_APPROX( (res=b.transpose()*b), MatrixType::Zero(cols,cols) );
|
||||
VERIFY_IS_APPROX( (res=b.transpose()*a.transpose()), MatrixType::Zero(cols,rows) );
|
||||
}
|
||||
|
||||
{
|
||||
MatrixType res, a(rows,cols), b(cols,0);
|
||||
res = a*b;
|
||||
VERIFY(res.rows()==rows && res.cols()==0);
|
||||
b.resize(0,rows);
|
||||
res = b*a;
|
||||
VERIFY(res.rows()==0 && res.cols()==cols);
|
||||
}
|
||||
|
||||
{
|
||||
Matrix<Scalar,PacketSize,0> a;
|
||||
Matrix<Scalar,0,1> b;
|
||||
Matrix<Scalar,PacketSize,1> res;
|
||||
VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(PacketSize,1) );
|
||||
VERIFY_IS_APPROX( (res=a.lazyProduct(b)), MatrixType::Zero(PacketSize,1) );
|
||||
}
|
||||
|
||||
{
|
||||
Matrix<Scalar,PacketSize1,0> a;
|
||||
Matrix<Scalar,0,1> b;
|
||||
Matrix<Scalar,PacketSize1,1> res;
|
||||
VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(PacketSize1,1) );
|
||||
VERIFY_IS_APPROX( (res=a.lazyProduct(b)), MatrixType::Zero(PacketSize1,1) );
|
||||
}
|
||||
|
||||
{
|
||||
Matrix<Scalar,PacketSize,Dynamic> a(PacketSize,0);
|
||||
Matrix<Scalar,Dynamic,1> b(0,1);
|
||||
Matrix<Scalar,PacketSize,1> res;
|
||||
VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(PacketSize,1) );
|
||||
VERIFY_IS_APPROX( (res=a.lazyProduct(b)), MatrixType::Zero(PacketSize,1) );
|
||||
}
|
||||
|
||||
{
|
||||
Matrix<Scalar,PacketSize1,Dynamic> a(PacketSize1,0);
|
||||
Matrix<Scalar,Dynamic,1> b(0,1);
|
||||
Matrix<Scalar,PacketSize1,1> res;
|
||||
VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(PacketSize1,1) );
|
||||
VERIFY_IS_APPROX( (res=a.lazyProduct(b)), MatrixType::Zero(PacketSize1,1) );
|
||||
}
|
||||
}
|
||||
|
||||
template<int>
|
||||
void bug_127()
|
||||
{
|
||||
// Bug 127
|
||||
//
|
||||
// a product of the form lhs*rhs with
|
||||
//
|
||||
// lhs:
|
||||
// rows = 1, cols = 4
|
||||
// RowsAtCompileTime = 1, ColsAtCompileTime = -1
|
||||
// MaxRowsAtCompileTime = 1, MaxColsAtCompileTime = 5
|
||||
//
|
||||
// rhs:
|
||||
// rows = 4, cols = 0
|
||||
// RowsAtCompileTime = -1, ColsAtCompileTime = -1
|
||||
// MaxRowsAtCompileTime = 5, MaxColsAtCompileTime = 1
|
||||
//
|
||||
// was failing on a runtime assertion, because it had been mis-compiled as a dot product because Product.h was using the
|
||||
// max-sizes to detect size 1 indicating vectors, and that didn't account for 0-sized object with max-size 1.
|
||||
|
||||
Matrix<float,1,Dynamic,RowMajor,1,5> a(1,4);
|
||||
Matrix<float,Dynamic,Dynamic,ColMajor,5,1> b(4,0);
|
||||
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:
|
||||
// http://forum.kde.org/viewtopic.php?f=74&t=107541
|
||||
// Recall the matrix*vector kernel avoid unaligned loads by loading two packets and then reassemble then.
|
||||
// There was a mistake in the computation of the valid range for fully unaligned objects: in some rare cases,
|
||||
// memory was read outside the allocated matrix memory. Though the values were not used, this might raise segfault.
|
||||
for(int m=450;m<460;++m)
|
||||
{
|
||||
for(int n=8;n<12;++n)
|
||||
{
|
||||
MatrixXf M(m, n);
|
||||
VectorXf v1(n), r1(500);
|
||||
RowVectorXf v2(m), r2(16);
|
||||
|
||||
M.setRandom();
|
||||
v1.setRandom();
|
||||
v2.setRandom();
|
||||
for(int o=0; o<4; ++o)
|
||||
{
|
||||
r1.segment(o,m).noalias() = M * v1;
|
||||
VERIFY_IS_APPROX(r1.segment(o,m), M * MatrixXf(v1));
|
||||
r2.segment(o,n).noalias() = v2 * M;
|
||||
VERIFY_IS_APPROX(r2.segment(o,n), MatrixXf(v2) * M);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(product_extra)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( product_extra(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_2( product_extra(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_2( mat_mat_scalar_scalar_product() );
|
||||
CALL_SUBTEST_3( product_extra(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
|
||||
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<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>() );
|
||||
|
||||
}
|
||||
131
libs/eigen/test/product_large.cpp
Normal file
131
libs/eigen/test/product_large.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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"
|
||||
#include <Eigen/LU>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template<int>
|
||||
void product_large_regressions()
|
||||
{
|
||||
{
|
||||
// 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());
|
||||
}
|
||||
|
||||
{
|
||||
// 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>(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,std::ptrdiff_t>(k1,m1,n1,1);
|
||||
}
|
||||
|
||||
{
|
||||
// test regression in row-vector by matrix (bad Map type)
|
||||
MatrixXf mat1(10,32); mat1.setRandom();
|
||||
MatrixXf mat2(32,32); mat2.setRandom();
|
||||
MatrixXf r1 = mat1.row(2)*mat2.transpose();
|
||||
VERIFY_IS_APPROX(r1, (mat1.row(2)*mat2.transpose()).eval());
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
template<int>
|
||||
void bug_1622() {
|
||||
typedef Matrix<double, 2, -1, 0, 2, -1> Mat2X;
|
||||
Mat2X x(2,2); x.setRandom();
|
||||
MatrixXd y(2,2); y.setRandom();
|
||||
const Mat2X K1 = x * y.inverse();
|
||||
const Matrix2d K2 = x * y.inverse();
|
||||
VERIFY_IS_APPROX(K1,K2);
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(product_large)
|
||||
{
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( product(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_2( product(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_2( product(MatrixXd(internal::random<int>(1,10), internal::random<int>(1,10))) );
|
||||
|
||||
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>() );
|
||||
|
||||
CALL_SUBTEST_6( bug_1622<1>() );
|
||||
|
||||
CALL_SUBTEST_7( product(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
|
||||
CALL_SUBTEST_8( product(Matrix<double,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_9( product(Matrix<std::complex<float>,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
CALL_SUBTEST_10( product(Matrix<std::complex<double>,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
|
||||
}
|
||||
|
||||
CALL_SUBTEST_6( product_large_regressions<0>() );
|
||||
|
||||
// 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
|
||||
}
|
||||
106
libs/eigen/test/product_mmtr.cpp
Normal file
106
libs/eigen/test/product_mmtr.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2010-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/.
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define CHECK_MMTR(DEST, TRI, OP) { \
|
||||
ref3 = DEST; \
|
||||
ref2 = ref1 = DEST; \
|
||||
DEST.template triangularView<TRI>() OP; \
|
||||
ref1 OP; \
|
||||
ref2.template triangularView<TRI>() \
|
||||
= ref1.template triangularView<TRI>(); \
|
||||
VERIFY_IS_APPROX(DEST,ref2); \
|
||||
\
|
||||
DEST = ref3; \
|
||||
ref3 = ref2; \
|
||||
ref3.diagonal() = DEST.diagonal(); \
|
||||
DEST.template triangularView<TRI|ZeroDiag>() OP; \
|
||||
VERIFY_IS_APPROX(DEST,ref3); \
|
||||
}
|
||||
|
||||
template<typename Scalar> void mmtr(int size)
|
||||
{
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> MatrixColMaj;
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic,RowMajor> MatrixRowMaj;
|
||||
|
||||
DenseIndex othersize = internal::random<DenseIndex>(1,200);
|
||||
|
||||
MatrixColMaj matc = MatrixColMaj::Zero(size, size);
|
||||
MatrixRowMaj matr = MatrixRowMaj::Zero(size, size);
|
||||
MatrixColMaj ref1(size, size), ref2(size, size), ref3(size,size);
|
||||
|
||||
MatrixColMaj soc(size,othersize); soc.setRandom();
|
||||
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>();
|
||||
|
||||
CHECK_MMTR(matc, Lower, = s*soc*sor.adjoint());
|
||||
CHECK_MMTR(matc, Upper, = s*(soc*soc.adjoint()));
|
||||
CHECK_MMTR(matr, Lower, = s*soc*soc.adjoint());
|
||||
CHECK_MMTR(matr, Upper, = soc*(s*sor.adjoint()));
|
||||
|
||||
CHECK_MMTR(matc, Lower, += s*soc*soc.adjoint());
|
||||
CHECK_MMTR(matc, Upper, += s*(soc*sor.transpose()));
|
||||
CHECK_MMTR(matr, Lower, += s*sor*soc.adjoint());
|
||||
CHECK_MMTR(matr, Upper, += soc*(s*soc.adjoint()));
|
||||
|
||||
CHECK_MMTR(matc, Lower, -= s*soc*soc.adjoint());
|
||||
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);
|
||||
|
||||
// destination with a non-default inner-stride
|
||||
// see bug 1741
|
||||
{
|
||||
typedef Matrix<Scalar,Dynamic,Dynamic> MatrixX;
|
||||
MatrixX buffer(2*size,2*size);
|
||||
Map<MatrixColMaj,0,Stride<Dynamic,Dynamic> > map1(buffer.data(),size,size,Stride<Dynamic,Dynamic>(2*size,2));
|
||||
buffer.setZero();
|
||||
CHECK_MMTR(map1, Lower, = s*soc*sor.adjoint());
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(product_mmtr)
|
||||
{
|
||||
for(int i = 0; i < g_repeat ; i++)
|
||||
{
|
||||
CALL_SUBTEST_1((mmtr<float>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
|
||||
CALL_SUBTEST_2((mmtr<double>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
|
||||
CALL_SUBTEST_3((mmtr<std::complex<float> >(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))));
|
||||
CALL_SUBTEST_4((mmtr<std::complex<double> >(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))));
|
||||
}
|
||||
}
|
||||
209
libs/eigen/test/product_notemporary.cpp
Normal file
209
libs/eigen/test/product_notemporary.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// 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 TEST_ENABLE_TEMPORARY_TRACKING
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename Dst, typename Lhs, typename Rhs>
|
||||
void check_scalar_multiple3(Dst &dst, const Lhs& A, const Rhs& B)
|
||||
{
|
||||
VERIFY_EVALUATION_COUNT( (dst.noalias() = A * B), 0);
|
||||
VERIFY_IS_APPROX( dst, (A.eval() * B.eval()).eval() );
|
||||
VERIFY_EVALUATION_COUNT( (dst.noalias() += A * B), 0);
|
||||
VERIFY_IS_APPROX( dst, 2*(A.eval() * B.eval()).eval() );
|
||||
VERIFY_EVALUATION_COUNT( (dst.noalias() -= A * B), 0);
|
||||
VERIFY_IS_APPROX( dst, (A.eval() * B.eval()).eval() );
|
||||
}
|
||||
|
||||
template<typename Dst, typename Lhs, typename Rhs, typename S2>
|
||||
void check_scalar_multiple2(Dst &dst, const Lhs& A, const Rhs& B, S2 s2)
|
||||
{
|
||||
CALL_SUBTEST( check_scalar_multiple3(dst, A, B) );
|
||||
CALL_SUBTEST( check_scalar_multiple3(dst, A, -B) );
|
||||
CALL_SUBTEST( check_scalar_multiple3(dst, A, s2*B) );
|
||||
CALL_SUBTEST( check_scalar_multiple3(dst, A, B*s2) );
|
||||
CALL_SUBTEST( check_scalar_multiple3(dst, A, (B*s2).conjugate()) );
|
||||
}
|
||||
|
||||
template<typename Dst, typename Lhs, typename Rhs, typename S1, typename S2>
|
||||
void check_scalar_multiple1(Dst &dst, const Lhs& A, const Rhs& B, S1 s1, S2 s2)
|
||||
{
|
||||
CALL_SUBTEST( check_scalar_multiple2(dst, A, B, s2) );
|
||||
CALL_SUBTEST( check_scalar_multiple2(dst, -A, B, s2) );
|
||||
CALL_SUBTEST( check_scalar_multiple2(dst, s1*A, B, s2) );
|
||||
CALL_SUBTEST( check_scalar_multiple2(dst, A*s1, B, s2) );
|
||||
CALL_SUBTEST( check_scalar_multiple2(dst, (A*s1).conjugate(), B, s2) );
|
||||
}
|
||||
|
||||
template<typename MatrixType> void product_notemporary(const MatrixType& m)
|
||||
{
|
||||
/* This test checks the number of temporaries created
|
||||
* during the evaluation of a complex expression */
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
|
||||
typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> ColMajorMatrixType;
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic, RowMajor> RowMajorMatrixType;
|
||||
|
||||
Index rows = m.rows();
|
||||
Index cols = m.cols();
|
||||
|
||||
ColMajorMatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols);
|
||||
RowVectorType rv1 = RowVectorType::Random(rows), rvres(rows);
|
||||
ColVectorType cv1 = ColVectorType::Random(cols), cvres(cols);
|
||||
RowMajorMatrixType rm3(rows, cols);
|
||||
|
||||
Scalar s1 = internal::random<Scalar>(),
|
||||
s2 = internal::random<Scalar>(),
|
||||
s3 = internal::random<Scalar>();
|
||||
|
||||
Index c0 = internal::random<Index>(4,cols-8),
|
||||
c1 = internal::random<Index>(8,cols-c0),
|
||||
r0 = internal::random<Index>(4,cols-8),
|
||||
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()), 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);
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() += s1 * (-m1*s3).adjoint() * (s2 * m2 * s3), 0);
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() -= s1 * (m1.transpose() * m2), 0);
|
||||
|
||||
VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() += -m1.block(r0,c0,r1,c1) * (s2*m2.block(r0,c0,r1,c1)).adjoint() ), 0);
|
||||
VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() -= s1 * m1.block(r0,c0,r1,c1) * m2.block(c0,r0,c1,r1) ), 0);
|
||||
|
||||
// NOTE this is because the Block expression is not handled yet by our expression analyser
|
||||
VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() = s1 * m1.block(r0,c0,r1,c1) * (s1*m2).block(c0,r0,c1,r1) ), 1);
|
||||
|
||||
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);
|
||||
|
||||
// NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products
|
||||
VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * (s2*m2.row(c0)).adjoint(), 1);
|
||||
|
||||
VERIFY_EVALUATION_COUNT( m1.template triangularView<Lower>().solveInPlace(m3), 0);
|
||||
VERIFY_EVALUATION_COUNT( m1.adjoint().template triangularView<Lower>().solveInPlace(m3.transpose()), 0);
|
||||
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2*s3).adjoint(), 0);
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() = s2 * m2.adjoint() * (s1 * m1.adjoint()).template selfadjointView<Upper>(), 0);
|
||||
VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template selfadjointView<Lower>() * m2.adjoint(), 0);
|
||||
|
||||
// NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products
|
||||
VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2.row(c0)*s3).adjoint(), 1);
|
||||
VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<Upper>() * (-m2.row(c0)*s3).adjoint(), 1);
|
||||
|
||||
VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() += m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * (s1*m2.block(r0,c0,r1,c1)), 0);
|
||||
VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * m2.block(r0,c0,r1,c1), 0);
|
||||
|
||||
VERIFY_EVALUATION_COUNT( m3.template selfadjointView<Lower>().rankUpdate(m2.adjoint()), 0);
|
||||
|
||||
// Here we will get 1 temporary for each resize operation of the lhs operator; resize(r1,c1) would lead to zero temporaries
|
||||
m3.resize(1,1);
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Lower>() * m2.block(r0,c0,r1,c1), 1);
|
||||
m3.resize(1,1);
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template triangularView<UnitUpper>() * m2.block(r0,c0,r1,c1), 1);
|
||||
|
||||
// Zero temporaries for lazy products ...
|
||||
m3.setRandom(rows,cols);
|
||||
VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) / (m3.transpose().lazyProduct(m3)).diagonal().sum(), 0 );
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() = m1.conjugate().lazyProduct(m2.conjugate()), 0);
|
||||
|
||||
// ... and even no temporary for even deeply (>=2) nested products
|
||||
VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) / (m3.transpose() * m3).diagonal().sum(), 0 );
|
||||
VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) / (m3.transpose() * m3).diagonal().array().abs().sum(), 0 );
|
||||
|
||||
// Zero temporaries for ... CoeffBasedProductMode
|
||||
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 );
|
||||
VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * cv1, 0 );
|
||||
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
|
||||
#ifdef EIGEN_ALLOCA
|
||||
bool temp_via_alloca = m3.rows()*sizeof(Scalar) <= EIGEN_STACK_ALLOCATION_LIMIT;
|
||||
#else
|
||||
bool temp_via_alloca = false;
|
||||
#endif
|
||||
m3 = cv1 * rv1;
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() = cv1 * rv1, 0 );
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() = (cv1+cv1) * (rv1+rv1), temp_via_alloca ? 0 : 1 );
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() = (m1*cv1) * (rv1), 1 );
|
||||
VERIFY_EVALUATION_COUNT( m3.noalias() += (m1*cv1) * (rv1), 1 );
|
||||
rm3 = cv1 * rv1;
|
||||
VERIFY_EVALUATION_COUNT( rm3.noalias() = cv1 * rv1, 0 );
|
||||
VERIFY_EVALUATION_COUNT( rm3.noalias() = (cv1+cv1) * (rv1+rv1), temp_via_alloca ? 0 : 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 );
|
||||
|
||||
// exhaustively check all scalar multiple combinations:
|
||||
{
|
||||
// Generic path:
|
||||
check_scalar_multiple1(m3, m1, m2, s1, s2);
|
||||
// Force fall back to coeff-based:
|
||||
typename ColMajorMatrixType::BlockXpr m3_blck = m3.block(r0,r0,1,1);
|
||||
check_scalar_multiple1(m3_blck, m1.block(r0,c0,1,1), m2.block(c0,r0,1,1), s1, s2);
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(product_notemporary)
|
||||
{
|
||||
int s;
|
||||
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)) );
|
||||
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)) );
|
||||
CALL_SUBTEST_4( product_notemporary(MatrixXcd(s,s)) );
|
||||
TEST_SET_BUT_UNUSED_VARIABLE(s)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user