Pull latest updates from upstream

This commit is contained in:
Benoit Steiner
2016-04-11 17:20:17 -07:00
340 changed files with 13835 additions and 5211 deletions

View File

@@ -226,7 +226,9 @@ ei_add_test(geo_homogeneous)
ei_add_test(stdvector)
ei_add_test(stdvector_overload)
ei_add_test(stdlist)
ei_add_test(stdlist_overload)
ei_add_test(stddeque)
ei_add_test(stddeque_overload)
ei_add_test(sparse_basic)
ei_add_test(sparse_block)
ei_add_test(sparse_vector)
@@ -323,10 +325,16 @@ if(EIGEN_TEST_EIGEN2)
endif()
# NVCC unit tests
option(EIGEN_TEST_NVCC "Enable NVCC support in unit tests" OFF)
if(EIGEN_TEST_NVCC)
# CUDA unit tests
option(EIGEN_TEST_CUDA "Enable CUDA support in unit tests" OFF)
option(EIGEN_TEST_CUDA_CLANG "Use clang instead of nvcc to compile the CUDA tests" OFF)
if(EIGEN_TEST_CUDA_CLANG AND NOT CMAKE_CXX_COMPILER MATCHES "clang")
message(WARNING "EIGEN_TEST_CUDA_CLANG is set, but CMAKE_CXX_COMPILER does not appear to be clang.")
endif()
if(EIGEN_TEST_CUDA)
find_package(CUDA 5.0)
if(CUDA_FOUND)
@@ -334,6 +342,9 @@ if(CUDA_FOUND)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CUDA_NVCC_FLAGS "-ccbin /usr/bin/clang" CACHE STRING "nvcc flags" FORCE)
endif()
if(EIGEN_TEST_CUDA_CLANG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 --cuda-gpu-arch=sm_30")
endif()
cuda_include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(EIGEN_ADD_TEST_FILENAME_EXTENSION "cu")
@@ -343,7 +354,7 @@ if(CUDA_FOUND)
endif(CUDA_FOUND)
endif(EIGEN_TEST_NVCC)
endif(EIGEN_TEST_CUDA)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/failtests)

View File

@@ -42,6 +42,17 @@ template<> struct adjoint_specific<false> {
VERIFY_IS_APPROX(v1, v1.norm() * v3);
VERIFY_IS_APPROX(v3, v1.normalized());
VERIFY_IS_APPROX(v3.norm(), RealScalar(1));
// check null inputs
VERIFY_IS_APPROX((v1*0).normalized(), (v1*0));
#if (!EIGEN_ARCH_i386) || defined(EIGEN_VECTORIZE)
RealScalar very_small = (std::numeric_limits<RealScalar>::min)();
VERIFY( (v1*very_small).norm() == 0 );
VERIFY_IS_APPROX((v1*very_small).normalized(), (v1*very_small));
v3 = v1*very_small;
v3.normalize();
VERIFY_IS_APPROX(v3, (v1*very_small));
#endif
// check compatibility of dot and adjoint
ref = NumTraits<Scalar>::IsInteger ? 0 : (std::max)((std::max)(v1.norm(),v2.norm()),(std::max)((square * v2).norm(),(square.adjoint() * v1).norm()));

View File

@@ -202,7 +202,7 @@ template<typename ArrayType> void array_real(const ArrayType& m)
m2 = ArrayType::Random(rows, cols),
m3(rows, cols),
m4 = m1;
m4 = (m4.abs()==Scalar(0)).select(1,m4);
Scalar s1 = internal::random<Scalar>();
@@ -217,6 +217,12 @@ template<typename ArrayType> void array_real(const ArrayType& m)
VERIFY_IS_APPROX(m1.sinh(), sinh(m1));
VERIFY_IS_APPROX(m1.cosh(), cosh(m1));
VERIFY_IS_APPROX(m1.tanh(), tanh(m1));
#ifdef EIGEN_HAS_C99_MATH
VERIFY_IS_APPROX(m1.lgamma(), lgamma(m1));
VERIFY_IS_APPROX(m1.digamma(), digamma(m1));
VERIFY_IS_APPROX(m1.erf(), erf(m1));
VERIFY_IS_APPROX(m1.erfc(), erfc(m1));
#endif // EIGEN_HAS_C99_MATH
VERIFY_IS_APPROX(m1.arg(), arg(m1));
VERIFY_IS_APPROX(m1.round(), round(m1));
VERIFY_IS_APPROX(m1.floor(), floor(m1));
@@ -289,7 +295,6 @@ template<typename ArrayType> void array_real(const ArrayType& m)
VERIFY_IS_APPROX(Eigen::pow(m1,2*exponents), m1.square().square());
VERIFY_IS_APPROX(m1.pow(2*exponents), m1.square().square());
VERIFY_IS_APPROX(pow(m1(0,0), exponents), ArrayType::Constant(rows,cols,m1(0,0)*m1(0,0)));
VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
VERIFY_IS_APPROX(pow(m3,RealScalar(0.5)), m3.sqrt());
@@ -304,7 +309,123 @@ template<typename ArrayType> void array_real(const ArrayType& m)
s1 += Scalar(tiny);
m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
#ifdef EIGEN_HAS_C99_MATH
// check special functions (comparing against numpy implementation)
if (!NumTraits<Scalar>::IsComplex) {
VERIFY_IS_APPROX(numext::digamma(Scalar(1)), RealScalar(-0.5772156649015329));
VERIFY_IS_APPROX(numext::digamma(Scalar(1.5)), RealScalar(0.03648997397857645));
VERIFY_IS_APPROX(numext::digamma(Scalar(4)), RealScalar(1.2561176684318));
VERIFY_IS_APPROX(numext::digamma(Scalar(-10.5)), RealScalar(2.398239129535781));
VERIFY_IS_APPROX(numext::digamma(Scalar(10000.5)), RealScalar(9.210340372392849));
VERIFY_IS_EQUAL(numext::digamma(Scalar(0)),
std::numeric_limits<RealScalar>::infinity());
VERIFY_IS_EQUAL(numext::digamma(Scalar(-1)),
std::numeric_limits<RealScalar>::infinity());
// Check the zeta function against scipy.special.zeta
VERIFY_IS_APPROX(numext::zeta(Scalar(1.5), Scalar(2)), RealScalar(1.61237534869));
VERIFY_IS_APPROX(numext::zeta(Scalar(4), Scalar(1.5)), RealScalar(0.234848505667));
VERIFY_IS_APPROX(numext::zeta(Scalar(10.5), Scalar(3)), RealScalar(1.03086757337e-5));
VERIFY_IS_APPROX(numext::zeta(Scalar(10000.5), Scalar(1.0001)), RealScalar(0.367879440865));
VERIFY_IS_APPROX(numext::zeta(Scalar(3), Scalar(-2.5)), RealScalar(0.054102025820864097));
VERIFY_IS_EQUAL(numext::zeta(Scalar(1), Scalar(1.2345)), // The second scalar does not matter
std::numeric_limits<RealScalar>::infinity());
VERIFY((numext::isnan)(numext::zeta(Scalar(0.9), Scalar(1.2345)))); // The second scalar does not matter
// Check the polygamma against scipy.special.polygamma examples
VERIFY_IS_APPROX(numext::polygamma(Scalar(1), Scalar(2)), RealScalar(0.644934066848));
VERIFY_IS_APPROX(numext::polygamma(Scalar(1), Scalar(3)), RealScalar(0.394934066848));
VERIFY_IS_APPROX(numext::polygamma(Scalar(1), Scalar(25.5)), RealScalar(0.0399946696496));
VERIFY((numext::isnan)(numext::polygamma(Scalar(1.5), Scalar(1.2345)))); // The second scalar does not matter
// Check the polygamma function over a larger range of values
VERIFY_IS_APPROX(numext::polygamma(Scalar(17), Scalar(4.7)), RealScalar(293.334565435));
VERIFY_IS_APPROX(numext::polygamma(Scalar(31), Scalar(11.8)), RealScalar(0.445487887616));
VERIFY_IS_APPROX(numext::polygamma(Scalar(28), Scalar(17.7)), RealScalar(-2.47810300902e-07));
VERIFY_IS_APPROX(numext::polygamma(Scalar(8), Scalar(30.2)), RealScalar(-8.29668781082e-09));
/* The following tests only pass for doubles because floats cannot handle the large values of
the gamma function.
VERIFY_IS_APPROX(numext::polygamma(Scalar(42), Scalar(15.8)), RealScalar(-0.434562276666));
VERIFY_IS_APPROX(numext::polygamma(Scalar(147), Scalar(54.1)), RealScalar(0.567742190178));
VERIFY_IS_APPROX(numext::polygamma(Scalar(170), Scalar(64)), RealScalar(-0.0108615497927));
*/
{
// Test various propreties of igamma & igammac. These are normalized
// gamma integrals where
// igammac(a, x) = Gamma(a, x) / Gamma(a)
// igamma(a, x) = gamma(a, x) / Gamma(a)
// where Gamma and gamma are considered the standard unnormalized
// upper and lower incomplete gamma functions, respectively.
ArrayType a = m1.abs() + 2;
ArrayType x = m2.abs() + 2;
ArrayType zero = ArrayType::Zero(rows, cols);
ArrayType one = ArrayType::Constant(rows, cols, Scalar(1.0));
ArrayType a_m1 = a - one;
ArrayType Gamma_a_x = Eigen::igammac(a, x) * a.lgamma().exp();
ArrayType Gamma_a_m1_x = Eigen::igammac(a_m1, x) * a_m1.lgamma().exp();
ArrayType gamma_a_x = Eigen::igamma(a, x) * a.lgamma().exp();
ArrayType gamma_a_m1_x = Eigen::igamma(a_m1, x) * a_m1.lgamma().exp();
// Gamma(a, 0) == Gamma(a)
VERIFY_IS_APPROX(Eigen::igammac(a, zero), one);
// Gamma(a, x) + gamma(a, x) == Gamma(a)
VERIFY_IS_APPROX(Gamma_a_x + gamma_a_x, a.lgamma().exp());
// Gamma(a, x) == (a - 1) * Gamma(a-1, x) + x^(a-1) * exp(-x)
VERIFY_IS_APPROX(Gamma_a_x, (a - 1) * Gamma_a_m1_x + x.pow(a-1) * (-x).exp());
// gamma(a, x) == (a - 1) * gamma(a-1, x) - x^(a-1) * exp(-x)
VERIFY_IS_APPROX(gamma_a_x, (a - 1) * gamma_a_m1_x - x.pow(a-1) * (-x).exp());
}
// Check exact values of igamma and igammac against a third party calculation.
Scalar a_s[] = {Scalar(0), Scalar(1), Scalar(1.5), Scalar(4), Scalar(0.0001), Scalar(1000.5)};
Scalar x_s[] = {Scalar(0), Scalar(1), Scalar(1.5), Scalar(4), Scalar(0.0001), Scalar(1000.5)};
// location i*6+j corresponds to a_s[i], x_s[j].
Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
Scalar igamma_s[][6] = {{0.0, nan, nan, nan, nan, nan},
{0.0, 0.6321205588285578, 0.7768698398515702,
0.9816843611112658, 9.999500016666262e-05, 1.0},
{0.0, 0.4275932955291202, 0.608374823728911,
0.9539882943107686, 7.522076445089201e-07, 1.0},
{0.0, 0.01898815687615381, 0.06564245437845008,
0.5665298796332909, 4.166333347221828e-18, 1.0},
{0.0, 0.9999780593618628, 0.9999899967080838,
0.9999996219837988, 0.9991370418689945, 1.0},
{0.0, 0.0, 0.0, 0.0, 0.0, 0.5042041932513908}};
Scalar igammac_s[][6] = {{nan, nan, nan, nan, nan, nan},
{1.0, 0.36787944117144233, 0.22313016014842982,
0.018315638888734182, 0.9999000049998333, 0.0},
{1.0, 0.5724067044708798, 0.3916251762710878,
0.04601170568923136, 0.9999992477923555, 0.0},
{1.0, 0.9810118431238462, 0.9343575456215499,
0.4334701203667089, 1.0, 0.0},
{1.0, 2.1940638138146658e-05, 1.0003291916285e-05,
3.7801620118431334e-07, 0.0008629581310054535,
0.0},
{1.0, 1.0, 1.0, 1.0, 1.0, 0.49579580674813944}};
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 6; ++j) {
if ((std::isnan)(igamma_s[i][j])) {
VERIFY((std::isnan)(numext::igamma(a_s[i], x_s[j])));
} else {
VERIFY_IS_APPROX(numext::igamma(a_s[i], x_s[j]), igamma_s[i][j]);
}
if ((std::isnan)(igammac_s[i][j])) {
VERIFY((std::isnan)(numext::igammac(a_s[i], x_s[j])));
} else {
VERIFY_IS_APPROX(numext::igammac(a_s[i], x_s[j]), igammac_s[i][j]);
}
}
}
}
#endif // EIGEN_HAS_C99_MATH
// check inplace transpose
m3 = m1;
m3.transposeInPlace();
@@ -331,8 +452,6 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
Array<RealScalar, -1, -1> m3(rows, cols);
Scalar s1 = internal::random<Scalar>();
for (Index i = 0; i < m.rows(); ++i)
for (Index j = 0; j < m.cols(); ++j)
m2(i,j) = sqrt(m1(i,j));
@@ -405,6 +524,7 @@ template<typename ArrayType> void array_complex(const ArrayType& m)
VERIFY_IS_APPROX( m1.sign() * m1.abs(), m1);
// scalar by array division
Scalar s1 = internal::random<Scalar>();
const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
s1 += Scalar(tiny);
m1 += ArrayType::Constant(rows,cols,Scalar(tiny));

View File

@@ -68,6 +68,16 @@ template<typename MatrixType> void array_for_matrix(const MatrixType& m)
const Scalar& ref_a2 = m.array().matrix().coeffRef(0,0);
VERIFY(&ref_a1 == &ref_m1);
VERIFY(&ref_a2 == &ref_m2);
// Check write accessors:
m1.array().coeffRef(0,0) = 1;
VERIFY_IS_APPROX(m1(0,0),Scalar(1));
m1.array()(0,0) = 2;
VERIFY_IS_APPROX(m1(0,0),Scalar(2));
m1.array().matrix().coeffRef(0,0) = 3;
VERIFY_IS_APPROX(m1(0,0),Scalar(3));
m1.array().matrix()(0,0) = 4;
VERIFY_IS_APPROX(m1(0,0),Scalar(4));
}
template<typename MatrixType> void comparisons(const MatrixType& m)

View File

@@ -181,6 +181,11 @@ template<typename MatrixType> void block(const MatrixType& m)
dm = m1.row(r1).segment(c1,c2-c1+1).transpose();
dv = m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0);
VERIFY_IS_EQUAL(dv, dm);
VERIFY_IS_EQUAL( (m1.template block<Dynamic,1>(1,0,0,1)), m1.block(1,0,0,1));
VERIFY_IS_EQUAL( (m1.template block<1,Dynamic>(0,1,1,0)), m1.block(0,1,1,0));
VERIFY_IS_EQUAL( ((m1*1).template block<Dynamic,1>(1,0,0,1)), m1.block(1,0,0,1));
VERIFY_IS_EQUAL( ((m1*1).template block<1,Dynamic>(0,1,1,0)), m1.block(0,1,1,0));
}

View File

@@ -41,13 +41,13 @@ template<typename T> void test_cholmod_T()
check_sparse_spd_solving(llt_colmajor_upper);
check_sparse_spd_solving(ldlt_colmajor_lower);
check_sparse_spd_solving(ldlt_colmajor_upper);
// check_sparse_spd_determinant(chol_colmajor_lower);
// check_sparse_spd_determinant(chol_colmajor_upper);
// check_sparse_spd_determinant(llt_colmajor_lower);
// check_sparse_spd_determinant(llt_colmajor_upper);
// check_sparse_spd_determinant(ldlt_colmajor_lower);
// check_sparse_spd_determinant(ldlt_colmajor_upper);
check_sparse_spd_determinant(chol_colmajor_lower);
check_sparse_spd_determinant(chol_colmajor_upper);
check_sparse_spd_determinant(llt_colmajor_lower);
check_sparse_spd_determinant(llt_colmajor_upper);
check_sparse_spd_determinant(ldlt_colmajor_lower);
check_sparse_spd_determinant(ldlt_colmajor_upper);
}
void test_cholmod_support()

View File

@@ -20,6 +20,8 @@ template<typename MatrixType> void diagonal(const MatrixType& m)
MatrixType m1 = MatrixType::Random(rows, cols),
m2 = MatrixType::Random(rows, cols);
Scalar s1 = internal::random<Scalar>();
//check diagonal()
VERIFY_IS_APPROX(m1.diagonal(), m1.transpose().diagonal());
m2.diagonal() = 2 * m1.diagonal();
@@ -58,6 +60,11 @@ template<typename MatrixType> void diagonal(const MatrixType& m)
VERIFY_IS_APPROX(m2.template diagonal<N2>(), static_cast<Scalar>(2) * m1.diagonal(N2));
m2.diagonal(N2)[0] *= 3;
VERIFY_IS_APPROX(m2.diagonal(N2)[0], static_cast<Scalar>(6) * m1.diagonal(N2)[0]);
m2.diagonal(N2).x() = s1;
VERIFY_IS_APPROX(m2.diagonal(N2).x(), s1);
m2.diagonal(N2).coeffRef(0) = Scalar(2)*s1;
VERIFY_IS_APPROX(m2.diagonal(N2).coeff(0), Scalar(2)*s1);
}
}

View File

@@ -31,7 +31,7 @@ void check_handmade_aligned_malloc()
void check_aligned_malloc()
{
for(int i = 1; i < 1000; i++)
for(int i = ALIGNMENT; i < 1000; i++)
{
char *p = (char*)internal::aligned_malloc(i);
VERIFY(size_t(p)%ALIGNMENT==0);
@@ -43,7 +43,7 @@ void check_aligned_malloc()
void check_aligned_new()
{
for(int i = 1; i < 1000; i++)
for(int i = ALIGNMENT; i < 1000; i++)
{
float *p = internal::aligned_new<float>(i);
VERIFY(size_t(p)%ALIGNMENT==0);
@@ -55,7 +55,7 @@ void check_aligned_new()
void check_aligned_stack_alloc()
{
for(int i = 1; i < 400; i++)
for(int i = ALIGNMENT; i < 400; i++)
{
ei_declare_aligned_stack_constructed_variable(float,p,i,0);
VERIFY(size_t(p)%ALIGNMENT==0);

View File

@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2015-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
@@ -15,16 +15,18 @@
template<typename T, typename I> void test_incomplete_cholesky_T()
{
typedef SparseMatrix<T,0,I> SparseMatrixType;
ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, AMDOrdering<I> > > cg_illt_lower_amd;
ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, NaturalOrdering<I> > > cg_illt_lower_nat;
ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, AMDOrdering<I> > > cg_illt_upper_amd;
ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, NaturalOrdering<I> > > cg_illt_upper_nat;
ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, AMDOrdering<I> > > cg_illt_lower_amd;
ConjugateGradient<SparseMatrixType, Lower, IncompleteCholesky<T, Lower, NaturalOrdering<I> > > cg_illt_lower_nat;
ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, AMDOrdering<I> > > cg_illt_upper_amd;
ConjugateGradient<SparseMatrixType, Upper, IncompleteCholesky<T, Upper, NaturalOrdering<I> > > cg_illt_upper_nat;
ConjugateGradient<SparseMatrixType, Upper|Lower, IncompleteCholesky<T, Lower, AMDOrdering<I> > > cg_illt_uplo_amd;
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_lower_amd) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_lower_nat) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_upper_amd) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_upper_nat) );
CALL_SUBTEST( check_sparse_spd_solving(cg_illt_uplo_amd) );
}
void test_incomplete_cholesky()
@@ -32,4 +34,32 @@ void test_incomplete_cholesky()
CALL_SUBTEST_1(( test_incomplete_cholesky_T<double,int>() ));
CALL_SUBTEST_2(( test_incomplete_cholesky_T<std::complex<double>, int>() ));
CALL_SUBTEST_3(( test_incomplete_cholesky_T<double,long int>() ));
#ifdef EIGEN_TEST_PART_1
// regression for bug 1150
for(int N = 1; N<20; ++N)
{
Eigen::MatrixXd b( N, N );
b.setOnes();
Eigen::SparseMatrix<double> m( N, N );
m.reserve(Eigen::VectorXi::Constant(N,4));
for( int i = 0; i < N; ++i )
{
m.insert( i, i ) = 1;
m.coeffRef( i, i / 2 ) = 2;
m.coeffRef( i, i / 3 ) = 2;
m.coeffRef( i, i / 4 ) = 2;
}
Eigen::SparseMatrix<double> A;
A = m * m.transpose();
Eigen::ConjugateGradient<Eigen::SparseMatrix<double>,
Eigen::Lower | Eigen::Upper,
Eigen::IncompleteCholesky<double> > solver( A );
VERIFY(solver.preconditioner().info() == Eigen::Success);
VERIFY(solver.info() == Eigen::Success);
}
#endif
}

View File

@@ -11,9 +11,10 @@
void test_is_same_dense()
{
MatrixXd m1(10,10);
Ref<MatrixXd> ref_m1(m1);
Ref<const MatrixXd> const_ref_m1(m1);
typedef Matrix<double,Dynamic,Dynamic,ColMajor> ColMatrixXd;
ColMatrixXd m1(10,10);
Ref<ColMatrixXd> ref_m1(m1);
Ref<const ColMatrixXd> const_ref_m1(m1);
VERIFY(is_same_dense(m1,m1));
VERIFY(is_same_dense(m1,ref_m1));
VERIFY(is_same_dense(const_ref_m1,m1));
@@ -22,9 +23,9 @@ void test_is_same_dense()
VERIFY(is_same_dense(m1.block(0,0,m1.rows(),m1.cols()),m1));
VERIFY(!is_same_dense(m1.row(0),m1.col(0)));
Ref<const MatrixXd> const_ref_m1_row(m1.row(1));
Ref<const ColMatrixXd> const_ref_m1_row(m1.row(1));
VERIFY(!is_same_dense(m1.row(1),const_ref_m1_row));
Ref<const MatrixXd> const_ref_m1_col(m1.col(1));
Ref<const ColMatrixXd> const_ref_m1_col(m1.col(1));
VERIFY(is_same_dense(m1.col(1),const_ref_m1_col));
}

View File

@@ -58,6 +58,10 @@
#define isnan(X) please_protect_your_isnan_with_parentheses
#define isinf(X) please_protect_your_isinf_with_parentheses
#define isfinite(X) please_protect_your_isfinite_with_parentheses
#ifdef M_PI
#undef M_PI
#endif
#define M_PI please_use_EIGEN_PI_instead_of_M_PI
#define FORBIDDEN_IDENTIFIER (this_identifier_is_forbidden_to_avoid_clashes) this_identifier_is_forbidden_to_avoid_clashes
// B0 is defined in POSIX header termios.h
@@ -331,11 +335,13 @@ inline bool test_isApprox(const std::complex<double>& a, const std::complex<doub
inline bool test_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b)
{ return internal::isMuchSmallerThan(a, b, test_precision<std::complex<double> >()); }
#ifndef EIGEN_TEST_NO_LONGDOUBLE
inline bool test_isApprox(const std::complex<long double>& a, const std::complex<long double>& b)
{ return internal::isApprox(a, b, test_precision<std::complex<long double> >()); }
inline bool test_isMuchSmallerThan(const std::complex<long double>& a, const std::complex<long double>& b)
{ return internal::isMuchSmallerThan(a, b, test_precision<std::complex<long double> >()); }
#endif
#endif
#ifndef EIGEN_TEST_NO_LONGDOUBLE
inline bool test_isApprox(const long double& a, const long double& b)

View File

@@ -40,7 +40,7 @@ template<typename VectorType> void map_class_vector(const VectorType& m)
VERIFY_IS_EQUAL(ma1, ma3);
VERIFY_IS_EQUAL(ma1, ma4);
#ifdef EIGEN_VECTORIZE
if(internal::packet_traits<Scalar>::Vectorizable)
if(internal::packet_traits<Scalar>::Vectorizable && size>=AlignedMax)
VERIFY_RAISES_ASSERT((Map<VectorType,AlignedMax>(array3unaligned, size)))
#endif

View File

@@ -44,6 +44,7 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
Mat_d md = mf.template cast<double>();
Mat_cf mcf = Mat_cf::Random(size,size);
Mat_cd mcd = mcf.template cast<complex<double> >();
Mat_cd rcd = mcd;
Vec_f vf = Vec_f::Random(size,1);
Vec_d vd = vf.template cast<double>();
Vec_cf vcf = Vec_cf::Random(size,1);
@@ -103,24 +104,23 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
VERIFY_IS_APPROX(mcd.array() *= md.array(), mcd2.array() *= md.array().template cast<std::complex<double> >());
// check matrix-matrix products
VERIFY_IS_APPROX(sd*md*mcd, (sd*md).template cast<CD>().eval()*mcd);
VERIFY_IS_APPROX(sd*mcd*md, sd*mcd*md.template cast<CD>());
VERIFY_IS_APPROX(scd*md*mcd, scd*md.template cast<CD>().eval()*mcd);
VERIFY_IS_APPROX(scd*mcd*md, scd*mcd*md.template cast<CD>());
VERIFY_IS_APPROX(sf*mf*mcf, sf*mf.template cast<CF>()*mcf);
VERIFY_IS_APPROX(sf*mcf*mf, sf*mcf*mf.template cast<CF>());
VERIFY_IS_APPROX(scf*mf*mcf, scf*mf.template cast<CF>()*mcf);
VERIFY_IS_APPROX(scf*mcf*mf, scf*mcf*mf.template cast<CF>());
VERIFY_IS_APPROX(sd*md.adjoint()*mcd, (sd*md).template cast<CD>().eval().adjoint()*mcd);
VERIFY_IS_APPROX(sd*mcd.adjoint()*md, sd*mcd.adjoint()*md.template cast<CD>());
VERIFY_IS_APPROX(sd*md.adjoint()*mcd.adjoint(), (sd*md).template cast<CD>().eval().adjoint()*mcd.adjoint());
VERIFY_IS_APPROX(sd*mcd.adjoint()*md.adjoint(), sd*mcd.adjoint()*md.template cast<CD>().adjoint());
VERIFY_IS_APPROX(sd*md*mcd.adjoint(), (sd*md).template cast<CD>().eval()*mcd.adjoint());
VERIFY_IS_APPROX(sd*mcd*md.adjoint(), sd*mcd*md.template cast<CD>().adjoint());
VERIFY_IS_APPROX(sf*mf.adjoint()*mcf, (sf*mf).template cast<CF>().eval().adjoint()*mcf);
VERIFY_IS_APPROX(sf*mcf.adjoint()*mf, sf*mcf.adjoint()*mf.template cast<CF>());
VERIFY_IS_APPROX(sf*mf.adjoint()*mcf.adjoint(), (sf*mf).template cast<CF>().eval().adjoint()*mcf.adjoint());
@@ -147,6 +147,39 @@ template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
VERIFY_IS_APPROX(scd*vcd.adjoint()*md, scd*vcd.adjoint()*md.template cast<CD>().eval());
VERIFY_IS_APPROX(sd*vd.adjoint()*mcd, sd*vd.adjoint().template cast<CD>().eval()*mcd);
VERIFY_IS_APPROX(scd*vd.adjoint()*mcd, scd*vd.adjoint().template cast<CD>().eval()*mcd);
VERIFY_IS_APPROX(sd*vcd.adjoint()*md.template triangularView<Upper>(), sd*vcd.adjoint()*md.template cast<CD>().eval().template triangularView<Upper>());
VERIFY_IS_APPROX(scd*vcd.adjoint()*md.template triangularView<Lower>(), scd*vcd.adjoint()*md.template cast<CD>().eval().template triangularView<Lower>());
VERIFY_IS_APPROX(sd*vd.adjoint()*mcd.template triangularView<Lower>(), sd*vd.adjoint().template cast<CD>().eval()*mcd.template triangularView<Lower>());
VERIFY_IS_APPROX(scd*vd.adjoint()*mcd.template triangularView<Upper>(), scd*vd.adjoint().template cast<CD>().eval()*mcd.template triangularView<Upper>());
// Not supported yet: trmm
// VERIFY_IS_APPROX(sd*mcd*md.template triangularView<Lower>(), sd*mcd*md.template cast<CD>().eval().template triangularView<Lower>());
// VERIFY_IS_APPROX(scd*mcd*md.template triangularView<Upper>(), scd*mcd*md.template cast<CD>().eval().template triangularView<Upper>());
// VERIFY_IS_APPROX(sd*md*mcd.template triangularView<Lower>(), sd*md.template cast<CD>().eval()*mcd.template triangularView<Lower>());
// VERIFY_IS_APPROX(scd*md*mcd.template triangularView<Upper>(), scd*md.template cast<CD>().eval()*mcd.template triangularView<Upper>());
// Not supported yet: symv
// VERIFY_IS_APPROX(sd*vcd.adjoint()*md.template selfadjointView<Upper>(), sd*vcd.adjoint()*md.template cast<CD>().eval().template selfadjointView<Upper>());
// VERIFY_IS_APPROX(scd*vcd.adjoint()*md.template selfadjointView<Lower>(), scd*vcd.adjoint()*md.template cast<CD>().eval().template selfadjointView<Lower>());
// VERIFY_IS_APPROX(sd*vd.adjoint()*mcd.template selfadjointView<Lower>(), sd*vd.adjoint().template cast<CD>().eval()*mcd.template selfadjointView<Lower>());
// VERIFY_IS_APPROX(scd*vd.adjoint()*mcd.template selfadjointView<Upper>(), scd*vd.adjoint().template cast<CD>().eval()*mcd.template selfadjointView<Upper>());
// Not supported yet: symm
// VERIFY_IS_APPROX(sd*vcd.adjoint()*md.template selfadjointView<Upper>(), sd*vcd.adjoint()*md.template cast<CD>().eval().template selfadjointView<Upper>());
// VERIFY_IS_APPROX(scd*vcd.adjoint()*md.template selfadjointView<Upper>(), scd*vcd.adjoint()*md.template cast<CD>().eval().template selfadjointView<Upper>());
// VERIFY_IS_APPROX(sd*vd.adjoint()*mcd.template selfadjointView<Upper>(), sd*vd.adjoint().template cast<CD>().eval()*mcd.template selfadjointView<Upper>());
// VERIFY_IS_APPROX(scd*vd.adjoint()*mcd.template selfadjointView<Upper>(), scd*vd.adjoint().template cast<CD>().eval()*mcd.template selfadjointView<Upper>());
rcd.setZero();
VERIFY_IS_APPROX(Mat_cd(rcd.template triangularView<Upper>() = sd * mcd * md),
Mat_cd((sd * mcd * md.template cast<CD>().eval()).template triangularView<Upper>()));
VERIFY_IS_APPROX(Mat_cd(rcd.template triangularView<Upper>() = sd * md * mcd),
Mat_cd((sd * md.template cast<CD>().eval() * mcd).template triangularView<Upper>()));
VERIFY_IS_APPROX(Mat_cd(rcd.template triangularView<Upper>() = scd * mcd * md),
Mat_cd((scd * mcd * md.template cast<CD>().eval()).template triangularView<Upper>()));
VERIFY_IS_APPROX(Mat_cd(rcd.template triangularView<Upper>() = scd * md * mcd),
Mat_cd((scd * md.template cast<CD>().eval() * mcd).template triangularView<Upper>()));
}
void test_mixingtypes()

View File

@@ -51,6 +51,7 @@ template <typename MatrixType> void run_nesting_ops_2(const MatrixType& _m)
Index rows = _m.rows();
Index cols = _m.cols();
MatrixType m1 = MatrixType::Random(rows,cols);
Matrix<Scalar,MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime,ColMajor> m2;
if((MatrixType::SizeAtCompileTime==Dynamic))
{
@@ -79,9 +80,9 @@ template <typename MatrixType> void run_nesting_ops_2(const MatrixType& _m)
}
VERIFY( verify_eval_type<2>(m1+m1, m1+m1) );
VERIFY( verify_eval_type<3>(m1+m1, m1) );
VERIFY( verify_eval_type<1>(m1*m1.transpose(), m1) );
VERIFY( verify_eval_type<1>(m1*(m1+m1).transpose(), m1) );
VERIFY( verify_eval_type<2>(m1*m1.transpose(), m1) );
VERIFY( verify_eval_type<1>(m1*m1.transpose(), m2) );
VERIFY( verify_eval_type<1>(m1*(m1+m1).transpose(), m2) );
VERIFY( verify_eval_type<2>(m1*m1.transpose(), m2) );
VERIFY( verify_eval_type<1>(m1+m1*m1, m1) );
VERIFY( verify_eval_type<1>(m1.template triangularView<Lower>().solve(m1), m1) );

View File

@@ -78,14 +78,15 @@ template<typename MatrixType> void nomalloc(const MatrixType& m)
VERIFY_IS_APPROX(m2,m2);
m2.template selfadjointView<Lower>().rankUpdate(m1.col(0),-1);
m2.template selfadjointView<Lower>().rankUpdate(m1.row(0),-1);
m2.template selfadjointView<Upper>().rankUpdate(m1.row(0),-1);
m2.template selfadjointView<Lower>().rankUpdate(m1.col(0), m1.col(0)); // rank-2
// The following fancy matrix-matrix products are not safe yet regarding static allocation
// m1 += m1.template triangularView<Upper>() * m2.col(;
// m1.template selfadjointView<Lower>().rankUpdate(m2);
// m1 += m1.template triangularView<Upper>() * m2;
// m1 += m1.template selfadjointView<Lower>() * m2;
// VERIFY_IS_APPROX(m1,m1);
m2.template selfadjointView<Lower>().rankUpdate(m1);
m2 += m2.template triangularView<Upper>() * m1;
m2.template triangularView<Upper>() = m2 * m2;
m1 += m1.template selfadjointView<Lower>() * m2;
VERIFY_IS_APPROX(m2,m2);
}
template<typename Scalar>

View File

@@ -48,30 +48,32 @@ void testVectorType(const VectorType& base)
VectorType m(base);
m.setLinSpaced(size,low,high);
if(!NumTraits<Scalar>::IsInteger)
{
VectorType n(size);
for (int i=0; i<size; ++i)
n(i) = low+i*step;
VERIFY_IS_APPROX(m,n);
}
VectorType n(size);
for (int i=0; i<size; ++i)
n(i) = low+i*step;
n(i) = size==1 ? low : (low + ((high-low)*Scalar(i))/(size-1));
VERIFY_IS_APPROX(m,n);
// random access version
m = VectorType::LinSpaced(size,low,high);
VERIFY_IS_APPROX(m,n);
// Assignment of a RowVectorXd to a MatrixXd (regression test for bug #79).
VERIFY( (MatrixXd(RowVectorXd::LinSpaced(3, 0, 1)) - RowVector3d(0, 0.5, 1)).norm() < std::numeric_limits<Scalar>::epsilon() );
// These guys sometimes fail! This is not good. Any ideas how to fix them!?
//VERIFY( m(m.size()-1) == high );
//VERIFY( m(0) == low );
VERIFY( internal::isApprox(m(m.size()-1),high) );
VERIFY( size==1 || internal::isApprox(m(0),low) );
// sequential access version
m = VectorType::LinSpaced(Sequential,size,low,high);
VERIFY_IS_APPROX(m,n);
// These guys sometimes fail! This is not good. Any ideas how to fix them!?
//VERIFY( m(m.size()-1) == high );
//VERIFY( m(0) == low );
VERIFY( internal::isApprox(m(m.size()-1),high) );
VERIFY( size==1 || internal::isApprox(m(0),low) );
// check whether everything works with row and col major vectors
Matrix<Scalar,Dynamic,1> row_vector(size);
@@ -126,5 +128,13 @@ void test_nullary()
CALL_SUBTEST_8( testVectorType(Vector4f()) );
CALL_SUBTEST_8( testVectorType(Matrix<float,8,1>()) );
CALL_SUBTEST_8( testVectorType(Matrix<float,1,1>()) );
CALL_SUBTEST_9( testVectorType(VectorXi(internal::random<int>(1,300))) );
CALL_SUBTEST_9( testVectorType(Matrix<int,1,1>()) );
}
#ifdef EIGEN_TEST_PART_6
// Assignment of a RowVectorXd to a MatrixXd (regression test for bug #79).
VERIFY( (MatrixXd(RowVectorXd::LinSpaced(3, 0, 1)) - RowVector3d(0, 0.5, 1)).norm() < std::numeric_limits<double>::epsilon() );
#endif
}

View File

@@ -177,7 +177,7 @@ template<typename Scalar> void packetmath()
internal::pstore(data2, internal::pset1<Packet>(data1[offset]));
VERIFY(areApprox(ref, data2, PacketSize) && "internal::pset1");
}
{
for (int i=0; i<PacketSize*4; ++i)
ref[i] = data1[i/PacketSize];
@@ -199,9 +199,9 @@ template<typename Scalar> void packetmath()
internal::pstore(data2+1*PacketSize, A1);
VERIFY(areApprox(ref, data2, 2*PacketSize) && "internal::pbroadcast2");
}
VERIFY(internal::isApprox(data1[0], internal::pfirst(internal::pload<Packet>(data1))) && "internal::pfirst");
if(PacketSize>1)
{
for(int offset=0;offset<4;++offset)
@@ -212,6 +212,7 @@ template<typename Scalar> void packetmath()
VERIFY(areApprox(ref, data2, PacketSize) && "ploaddup");
}
}
if(PacketSize>2)
{
for(int offset=0;offset<4;++offset)
@@ -227,7 +228,7 @@ template<typename Scalar> void packetmath()
for (int i=0; i<PacketSize; ++i)
ref[0] += data1[i];
VERIFY(isApproxAbs(ref[0], internal::predux(internal::pload<Packet>(data1)), refvalue) && "internal::predux");
{
for (int i=0; i<4; ++i)
ref[i] = 0;
@@ -325,6 +326,12 @@ template<typename Scalar> void packetmath_real()
data2[i] = internal::random<Scalar>(-87,88);
}
CHECK_CWISE1_IF(PacketTraits::HasExp, std::exp, internal::pexp);
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
data2[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
}
CHECK_CWISE1_IF(PacketTraits::HasTanh, std::tanh, internal::ptanh);
if(PacketTraits::HasExp && PacketTraits::size>=2)
{
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
@@ -338,7 +345,7 @@ template<typename Scalar> void packetmath_real()
data1[1] = 0;
h.store(data2, internal::pexp(h.load(data1)));
VERIFY_IS_EQUAL(std::exp(-std::numeric_limits<Scalar>::epsilon()), data2[0]);
VERIFY_IS_EQUAL(std::exp(0), data2[1]);
VERIFY_IS_EQUAL(std::exp(Scalar(0)), data2[1]);
data1[0] = (std::numeric_limits<Scalar>::min)();
data1[1] = -(std::numeric_limits<Scalar>::min)();
@@ -353,15 +360,43 @@ template<typename Scalar> void packetmath_real()
VERIFY_IS_EQUAL(std::exp(-std::numeric_limits<Scalar>::denorm_min()), data2[1]);
}
#ifdef EIGEN_HAS_C99_MATH
{
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
packet_helper<internal::packet_traits<Scalar>::HasLGamma,Packet> h;
h.store(data2, internal::plgamma(h.load(data1)));
VERIFY((numext::isnan)(data2[0]));
}
{
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
packet_helper<internal::packet_traits<Scalar>::HasErf,Packet> h;
h.store(data2, internal::perf(h.load(data1)));
VERIFY((numext::isnan)(data2[0]));
}
{
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
packet_helper<internal::packet_traits<Scalar>::HasErfc,Packet> h;
h.store(data2, internal::perfc(h.load(data1)));
VERIFY((numext::isnan)(data2[0]));
}
#endif // EIGEN_HAS_C99_MATH
for (int i=0; i<size; ++i)
{
data1[i] = internal::random<Scalar>(0,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
data2[i] = internal::random<Scalar>(0,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
}
if(internal::random<float>(0,1)<0.1)
data1[internal::random<int>(0, PacketSize)] = 0;
CHECK_CWISE1_IF(PacketTraits::HasSqrt, std::sqrt, internal::psqrt);
CHECK_CWISE1_IF(PacketTraits::HasLog, std::log, internal::plog);
#if defined(EIGEN_HAS_C99_MATH) && (__cplusplus > 199711L)
CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasLGamma, std::lgamma, internal::plgamma);
CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasErf, std::erf, internal::perf);
CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasErfc, std::erfc, internal::perfc);
#endif
if(PacketTraits::HasLog && PacketTraits::size>=2)
{
data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
@@ -375,7 +410,7 @@ template<typename Scalar> void packetmath_real()
data1[1] = 0;
h.store(data2, internal::plog(h.load(data1)));
VERIFY((numext::isnan)(data2[0]));
VERIFY_IS_EQUAL(std::log(0), data2[1]);
VERIFY_IS_EQUAL(std::log(Scalar(0)), data2[1]);
data1[0] = (std::numeric_limits<Scalar>::min)();
data1[1] = -(std::numeric_limits<Scalar>::min)();
@@ -397,6 +432,7 @@ template<typename Scalar> void packetmath_real()
VERIFY((numext::isnan)(data2[0]));
VERIFY((numext::isnan)(data2[1]));
#endif
}
}

View File

@@ -27,6 +27,14 @@ template<typename T> void test_pastix_T()
check_sparse_spd_solving(pastix_llt_upper);
check_sparse_spd_solving(pastix_ldlt_upper);
check_sparse_square_solving(pastix_lu);
// Some compilation check:
pastix_llt_lower.iparm();
pastix_llt_lower.dparm();
pastix_ldlt_lower.iparm();
pastix_ldlt_lower.dparm();
pastix_lu.iparm();
pastix_lu.dparm();
}
// There is no support for selfadjoint matrices with PaStiX.

View File

@@ -144,15 +144,56 @@ template<typename MatrixType> void product(const MatrixType& m)
VERIFY_IS_APPROX(res.col(r).noalias() = square.adjoint() * square.col(r), (square.adjoint() * square.col(r)).eval());
VERIFY_IS_APPROX(res.col(r).noalias() = square * square.col(r), (square * square.col(r)).eval());
// vector at runtime (see bug 1166)
{
RowSquareMatrixType ref(square);
ColSquareMatrixType ref2(square2);
ref = res = square;
VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.col(0).transpose() * square.transpose(), (ref.row(0) = m1.col(0).transpose() * square.transpose()));
VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.block(0,0,rows,1).transpose() * square.transpose(), (ref.row(0) = m1.col(0).transpose() * square.transpose()));
VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.col(0).transpose() * square, (ref.row(0) = m1.col(0).transpose() * square));
VERIFY_IS_APPROX(res.block(0,0,1,rows).noalias() = m1.block(0,0,rows,1).transpose() * square, (ref.row(0) = m1.col(0).transpose() * square));
ref2 = res2 = square2;
VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.row(0) * square2.transpose(), (ref2.row(0) = m1.row(0) * square2.transpose()));
VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.block(0,0,1,cols) * square2.transpose(), (ref2.row(0) = m1.row(0) * square2.transpose()));
VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.row(0) * square2, (ref2.row(0) = m1.row(0) * square2));
VERIFY_IS_APPROX(res2.block(0,0,1,cols).noalias() = m1.block(0,0,1,cols) * square2, (ref2.row(0) = m1.row(0) * square2));
}
// inner product
Scalar x = square2.row(c) * square2.col(c2);
VERIFY_IS_APPROX(x, square2.row(c).transpose().cwiseProduct(square2.col(c2)).sum());
{
Scalar x = square2.row(c) * square2.col(c2);
VERIFY_IS_APPROX(x, square2.row(c).transpose().cwiseProduct(square2.col(c2)).sum());
}
// outer product
VERIFY_IS_APPROX(m1.col(c) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
VERIFY_IS_APPROX(m1.row(r).transpose() * m1.col(c).transpose(), m1.block(r,0,1,cols).transpose() * m1.block(0,c,rows,1).transpose());
VERIFY_IS_APPROX(m1.block(0,c,rows,1) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
VERIFY_IS_APPROX(m1.col(c) * m1.block(r,0,1,cols), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
VERIFY_IS_APPROX(m1.leftCols(1) * m1.row(r), m1.block(0,0,rows,1) * m1.block(r,0,1,cols));
VERIFY_IS_APPROX(m1.col(c) * m1.topRows(1), m1.block(0,c,rows,1) * m1.block(0,0,1,cols));
{
VERIFY_IS_APPROX(m1.col(c) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
VERIFY_IS_APPROX(m1.row(r).transpose() * m1.col(c).transpose(), m1.block(r,0,1,cols).transpose() * m1.block(0,c,rows,1).transpose());
VERIFY_IS_APPROX(m1.block(0,c,rows,1) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
VERIFY_IS_APPROX(m1.col(c) * m1.block(r,0,1,cols), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
VERIFY_IS_APPROX(m1.leftCols(1) * m1.row(r), m1.block(0,0,rows,1) * m1.block(r,0,1,cols));
VERIFY_IS_APPROX(m1.col(c) * m1.topRows(1), m1.block(0,c,rows,1) * m1.block(0,0,1,cols));
}
// Aliasing
{
ColVectorType x(cols); x.setRandom();
ColVectorType z(x);
ColVectorType y(cols); y.setZero();
ColSquareMatrixType A(cols,cols); A.setRandom();
// CwiseBinaryOp
VERIFY_IS_APPROX(x = y + A*x, A*z);
x = z;
// CwiseUnaryOp
VERIFY_IS_APPROX(x = Scalar(1.)*(A*x), A*z);
}
// regression for blas_trais
{
VERIFY_IS_APPROX(square * (square*square).transpose(), square * square.transpose() * square.transpose());
VERIFY_IS_APPROX(square * (-(square*square)), -square * square * square);
VERIFY_IS_APPROX(square * (s1*(square*square)), s1 * square * square * square);
VERIFY_IS_APPROX(square * (square*square).conjugate(), square * square.conjugate() * square.conjugate());
}
}

View File

@@ -9,6 +9,27 @@
#include "product.h"
template<typename T>
void test_aliasing()
{
int rows = internal::random<int>(1,12);
int cols = internal::random<int>(1,12);
typedef Matrix<T,Dynamic,Dynamic> MatrixType;
typedef Matrix<T,Dynamic,1> VectorType;
VectorType x(cols); x.setRandom();
VectorType z(x);
VectorType y(rows); y.setZero();
MatrixType A(rows,cols); A.setRandom();
// CwiseBinaryOp
VERIFY_IS_APPROX(x = y + A*x, A*z); // OK because "y + A*x" is marked as "assume-aliasing"
x = z;
// CwiseUnaryOp
VERIFY_IS_APPROX(x = T(1.)*(A*x), A*z); // OK because 1*(A*x) is replaced by (1*A*x) which is a Product<> expression
x = z;
// VERIFY_IS_APPROX(x = y-A*x, -A*z); // Not OK in 3.3 because x is resized before A*x gets evaluated
x = z;
}
void test_product_large()
{
for(int i = 0; i < g_repeat; i++) {
@@ -17,6 +38,8 @@ void test_product_large()
CALL_SUBTEST_3( product(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_4( product(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
CALL_SUBTEST_5( product(Matrix<float,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_1( test_aliasing<float>() );
}
#if defined EIGEN_TEST_PART_6

View File

@@ -43,10 +43,16 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m)
r1 = internal::random<Index>(8,rows-r0);
VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()).transpose(), 1);
VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);
VERIFY_EVALUATION_COUNT( m3 = s1 * (m1 * m2.transpose()), 1);
// VERIFY_EVALUATION_COUNT( m3 = m3 + s1 * (m1 * m2.transpose()), 1);
VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);
VERIFY_EVALUATION_COUNT( m3 = m3 + (m1 * m2.adjoint()), 1);
VERIFY_EVALUATION_COUNT( m3 = m3 + (m1 * m2.adjoint()).transpose(), 1);
VERIFY_EVALUATION_COUNT( m3.noalias() = m3 + m1 * m2.transpose(), 0);
VERIFY_EVALUATION_COUNT( m3.noalias() += m3 + m1 * m2.transpose(), 0);
VERIFY_EVALUATION_COUNT( m3.noalias() -= m3 + m1 * m2.transpose(), 0);

View File

@@ -10,6 +10,86 @@
#include "main.h"
#include <Eigen/QR>
#include <Eigen/SVD>
template <typename MatrixType>
void cod() {
typedef typename MatrixType::Index Index;
Index rows = internal::random<Index>(2, EIGEN_TEST_MAX_SIZE);
Index cols = internal::random<Index>(2, EIGEN_TEST_MAX_SIZE);
Index cols2 = internal::random<Index>(2, EIGEN_TEST_MAX_SIZE);
Index rank = internal::random<Index>(1, (std::min)(rows, cols) - 1);
typedef typename MatrixType::Scalar Scalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime,
MatrixType::RowsAtCompileTime>
MatrixQType;
MatrixType matrix;
createRandomPIMatrixOfRank(rank, rows, cols, matrix);
CompleteOrthogonalDecomposition<MatrixType> cod(matrix);
VERIFY(rank == cod.rank());
VERIFY(cols - cod.rank() == cod.dimensionOfKernel());
VERIFY(!cod.isInjective());
VERIFY(!cod.isInvertible());
VERIFY(!cod.isSurjective());
MatrixQType q = cod.householderQ();
VERIFY_IS_UNITARY(q);
MatrixType z = cod.matrixZ();
VERIFY_IS_UNITARY(z);
MatrixType t;
t.setZero(rows, cols);
t.topLeftCorner(rank, rank) =
cod.matrixT().topLeftCorner(rank, rank).template triangularView<Upper>();
MatrixType c = q * t * z * cod.colsPermutation().inverse();
VERIFY_IS_APPROX(matrix, c);
MatrixType exact_solution = MatrixType::Random(cols, cols2);
MatrixType rhs = matrix * exact_solution;
MatrixType cod_solution = cod.solve(rhs);
VERIFY_IS_APPROX(rhs, matrix * cod_solution);
// Verify that we get the same minimum-norm solution as the SVD.
JacobiSVD<MatrixType> svd(matrix, ComputeThinU | ComputeThinV);
MatrixType svd_solution = svd.solve(rhs);
VERIFY_IS_APPROX(cod_solution, svd_solution);
MatrixType pinv = cod.pseudoInverse();
VERIFY_IS_APPROX(cod_solution, pinv * rhs);
}
template <typename MatrixType, int Cols2>
void cod_fixedsize() {
enum {
Rows = MatrixType::RowsAtCompileTime,
Cols = MatrixType::ColsAtCompileTime
};
typedef typename MatrixType::Scalar Scalar;
int rank = internal::random<int>(1, (std::min)(int(Rows), int(Cols)) - 1);
Matrix<Scalar, Rows, Cols> matrix;
createRandomPIMatrixOfRank(rank, Rows, Cols, matrix);
CompleteOrthogonalDecomposition<Matrix<Scalar, Rows, Cols> > cod(matrix);
VERIFY(rank == cod.rank());
VERIFY(Cols - cod.rank() == cod.dimensionOfKernel());
VERIFY(cod.isInjective() == (rank == Rows));
VERIFY(cod.isSurjective() == (rank == Cols));
VERIFY(cod.isInvertible() == (cod.isInjective() && cod.isSurjective()));
Matrix<Scalar, Cols, Cols2> exact_solution;
exact_solution.setRandom(Cols, Cols2);
Matrix<Scalar, Rows, Cols2> rhs = matrix * exact_solution;
Matrix<Scalar, Cols, Cols2> cod_solution = cod.solve(rhs);
VERIFY_IS_APPROX(rhs, matrix * cod_solution);
// Verify that we get the same minimum-norm solution as the SVD.
JacobiSVD<MatrixType> svd(matrix, ComputeFullU | ComputeFullV);
Matrix<Scalar, Cols, Cols2> svd_solution = svd.solve(rhs);
VERIFY_IS_APPROX(cod_solution, svd_solution);
}
template<typename MatrixType> void qr()
{
@@ -19,6 +99,7 @@ template<typename MatrixType> void qr()
Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
MatrixType m1;
createRandomPIMatrixOfRank(rank,rows,cols,m1);
@@ -36,6 +117,24 @@ template<typename MatrixType> void qr()
MatrixType c = q * r * qr.colsPermutation().inverse();
VERIFY_IS_APPROX(m1, c);
// Verify that the absolute value of the diagonal elements in R are
// non-increasing until they reach the singularity threshold.
RealScalar threshold =
std::sqrt(RealScalar(rows)) * (std::abs)(r(0, 0)) * NumTraits<Scalar>::epsilon();
for (Index i = 0; i < (std::min)(rows, cols) - 1; ++i) {
RealScalar x = (std::abs)(r(i, i));
RealScalar y = (std::abs)(r(i + 1, i + 1));
if (x < threshold && y < threshold) continue;
if (!test_isApproxOrLessThan(y, x)) {
for (Index j = 0; j < (std::min)(rows, cols); ++j) {
std::cout << "i = " << j << ", |r_ii| = " << (std::abs)(r(j, j)) << std::endl;
}
std::cout << "Failure at i=" << i << ", rank=" << rank
<< ", threshold=" << threshold << std::endl;
}
VERIFY_IS_APPROX_OR_LESS_THAN(y, x);
}
MatrixType m2 = MatrixType::Random(cols,cols2);
MatrixType m3 = m1*m2;
m2 = MatrixType::Random(cols,cols2);
@@ -47,6 +146,7 @@ template<typename MatrixType, int Cols2> void qr_fixedsize()
{
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
int rank = internal::random<int>(1, (std::min)(int(Rows), int(Cols))-1);
Matrix<Scalar,Rows,Cols> m1;
createRandomPIMatrixOfRank(rank,Rows,Cols,m1);
@@ -66,6 +166,67 @@ template<typename MatrixType, int Cols2> void qr_fixedsize()
m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
m2 = qr.solve(m3);
VERIFY_IS_APPROX(m3, m1*m2);
// Verify that the absolute value of the diagonal elements in R are
// non-increasing until they reache the singularity threshold.
RealScalar threshold =
std::sqrt(RealScalar(Rows)) * (std::abs)(r(0, 0)) * NumTraits<Scalar>::epsilon();
for (Index i = 0; i < (std::min)(int(Rows), int(Cols)) - 1; ++i) {
RealScalar x = (std::abs)(r(i, i));
RealScalar y = (std::abs)(r(i + 1, i + 1));
if (x < threshold && y < threshold) continue;
if (!test_isApproxOrLessThan(y, x)) {
for (Index j = 0; j < (std::min)(int(Rows), int(Cols)); ++j) {
std::cout << "i = " << j << ", |r_ii| = " << (std::abs)(r(j, j)) << std::endl;
}
std::cout << "Failure at i=" << i << ", rank=" << rank
<< ", threshold=" << threshold << std::endl;
}
VERIFY_IS_APPROX_OR_LESS_THAN(y, x);
}
}
// This test is meant to verify that pivots are chosen such that
// even for a graded matrix, the diagonal of R falls of roughly
// monotonically until it reaches the threshold for singularity.
// We use the so-called Kahan matrix, which is a famous counter-example
// for rank-revealing QR. See
// http://www.netlib.org/lapack/lawnspdf/lawn176.pdf
// page 3 for more detail.
template<typename MatrixType> void qr_kahan_matrix()
{
typedef typename MatrixType::Index Index;
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
Index rows = 300, cols = rows;
MatrixType m1;
m1.setZero(rows,cols);
RealScalar s = std::pow(NumTraits<RealScalar>::epsilon(), 1.0 / rows);
RealScalar c = std::sqrt(1 - s*s);
for (Index i = 0; i < rows; ++i) {
m1(i, i) = pow(s, i);
m1.row(i).tail(rows - i - 1) = -pow(s, i) * c * MatrixType::Ones(1, rows - i - 1);
}
m1 = (m1 + m1.transpose()).eval();
ColPivHouseholderQR<MatrixType> qr(m1);
MatrixType r = qr.matrixQR().template triangularView<Upper>();
RealScalar threshold =
std::sqrt(RealScalar(rows)) * (std::abs)(r(0, 0)) * NumTraits<Scalar>::epsilon();
for (Index i = 0; i < (std::min)(rows, cols) - 1; ++i) {
RealScalar x = (std::abs)(r(i, i));
RealScalar y = (std::abs)(r(i + 1, i + 1));
if (x < threshold && y < threshold) continue;
if (!test_isApproxOrLessThan(y, x)) {
for (Index j = 0; j < (std::min)(rows, cols); ++j) {
std::cout << "i = " << j << ", |r_ii| = " << (std::abs)(r(j, j)) << std::endl;
}
std::cout << "Failure at i=" << i << ", rank=" << qr.rank()
<< ", threshold=" << threshold << std::endl;
}
VERIFY_IS_APPROX_OR_LESS_THAN(y, x);
}
}
template<typename MatrixType> void qr_invertible()
@@ -131,6 +292,15 @@ void test_qr_colpivoting()
CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,1,1>, 1 >() ));
}
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( cod<MatrixXf>() );
CALL_SUBTEST_2( cod<MatrixXd>() );
CALL_SUBTEST_3( cod<MatrixXcd>() );
CALL_SUBTEST_4(( cod_fixedsize<Matrix<float,3,5>, 4 >() ));
CALL_SUBTEST_5(( cod_fixedsize<Matrix<double,6,2>, 3 >() ));
CALL_SUBTEST_5(( cod_fixedsize<Matrix<double,1,1>, 1 >() ));
}
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
CALL_SUBTEST_2( qr_invertible<MatrixXd>() );
@@ -147,4 +317,7 @@ void test_qr_colpivoting()
// Test problem size constructors
CALL_SUBTEST_9(ColPivHouseholderQR<MatrixXf>(10, 20));
CALL_SUBTEST_1( qr_kahan_matrix<MatrixXf>() );
CALL_SUBTEST_2( qr_kahan_matrix<MatrixXd>() );
}

View File

@@ -21,8 +21,8 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
const Index rows = ref.rows();
const Index cols = ref.cols();
const Index inner = ref.innerSize();
const Index outer = ref.outerSize();
//const Index inner = ref.innerSize();
//const Index outer = ref.outerSize();
typedef typename SparseMatrixType::Scalar Scalar;
enum { Flags = SparseMatrixType::Flags };
@@ -192,6 +192,11 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
VERIFY_IS_APPROX(refM4.cwiseProduct(m3), refM4.cwiseProduct(refM3));
// VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
VERIFY_IS_APPROX(refM4 + m3, refM4 + refM3);
VERIFY_IS_APPROX(m3 + refM4, refM3 + refM4);
VERIFY_IS_APPROX(refM4 - m3, refM4 - refM3);
VERIFY_IS_APPROX(m3 - refM4, refM3 - refM4);
// test aliasing
VERIFY_IS_APPROX((m1 = -m1), (refM1 = -refM1));
VERIFY_IS_APPROX((m1 = m1.transpose()), (refM1 = refM1.transpose().eval()));
@@ -322,7 +327,6 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
m3 = m2.template triangularView<Upper>();
VERIFY_IS_APPROX(m3, refMat3);
if(inner>=outer) // FIXME this should be implemented for outer>inner as well
{
refMat3 = refMat2.template triangularView<UnitUpper>();
m3 = m2.template triangularView<UnitUpper>();
@@ -455,6 +459,33 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
refMat1.setIdentity();
VERIFY_IS_APPROX(m1, refMat1);
}
// test array/vector of InnerIterator
{
typedef typename SparseMatrixType::InnerIterator IteratorType;
DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
SparseMatrixType m2(rows, cols);
initSparse<Scalar>(density, refMat2, m2);
IteratorType static_array[2];
static_array[0] = IteratorType(m2,0);
static_array[1] = IteratorType(m2,m2.outerSize()-1);
VERIFY( static_array[0] || m2.innerVector(static_array[0].outer()).nonZeros() == 0 );
VERIFY( static_array[1] || m2.innerVector(static_array[1].outer()).nonZeros() == 0 );
if(static_array[0] && static_array[1])
{
++(static_array[1]);
static_array[1] = IteratorType(m2,0);
VERIFY( static_array[1] );
VERIFY( static_array[1].index() == static_array[0].index() );
VERIFY( static_array[1].outer() == static_array[0].outer() );
VERIFY( static_array[1].value() == static_array[0].value() );
}
std::vector<IteratorType> iters(2);
iters[0] = IteratorType(m2,0);
iters[1] = IteratorType(m2,m2.outerSize()-1);
}
}

View File

@@ -9,14 +9,14 @@
#include "sparse.h"
template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
template<typename Scalar,typename StorageIndex> void sparse_vector(int rows, int cols)
{
double densityMat = (std::max)(8./(rows*cols), 0.01);
double densityVec = (std::max)(8./float(rows), 0.1);
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
typedef SparseVector<Scalar,0,Index> SparseVectorType;
typedef SparseMatrix<Scalar,0,Index> SparseMatrixType;
typedef SparseVector<Scalar,0,StorageIndex> SparseVectorType;
typedef SparseMatrix<Scalar,0,StorageIndex> SparseMatrixType;
Scalar eps = 1e-6;
SparseMatrixType m1(rows,rows);
@@ -87,8 +87,10 @@ template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
VERIFY_IS_APPROX(m1*v2, refM1*refV2);
VERIFY_IS_APPROX(v1.dot(m1*v2), refV1.dot(refM1*refV2));
int i = internal::random<int>(0,rows-1);
VERIFY_IS_APPROX(v1.dot(m1.col(i)), refV1.dot(refM1.col(i)));
{
int i = internal::random<int>(0,rows-1);
VERIFY_IS_APPROX(v1.dot(m1.col(i)), refV1.dot(refM1.col(i)));
}
VERIFY_IS_APPROX(v1.squaredNorm(), refV1.squaredNorm());
@@ -111,15 +113,51 @@ template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
VERIFY_IS_APPROX(refV3 = v1.transpose(),v1.toDense());
VERIFY_IS_APPROX(DenseVector(v1),v1.toDense());
// test conservative resize
{
std::vector<StorageIndex> inc;
if(rows > 3)
inc.push_back(-3);
inc.push_back(0);
inc.push_back(3);
inc.push_back(1);
inc.push_back(10);
for(std::size_t i = 0; i< inc.size(); i++) {
StorageIndex incRows = inc[i];
SparseVectorType vec1(rows);
DenseVector refVec1 = DenseVector::Zero(rows);
initSparse<Scalar>(densityVec, refVec1, vec1);
vec1.conservativeResize(rows+incRows);
refVec1.conservativeResize(rows+incRows);
if (incRows > 0) refVec1.tail(incRows).setZero();
VERIFY_IS_APPROX(vec1, refVec1);
// Insert new values
if (incRows > 0)
vec1.insert(vec1.rows()-1) = refVec1(refVec1.rows()-1) = 1;
VERIFY_IS_APPROX(vec1, refVec1);
}
}
}
void test_sparse_vector()
{
for(int i = 0; i < g_repeat; i++) {
int r = Eigen::internal::random<int>(1,500), c = Eigen::internal::random<int>(1,500);
if(Eigen::internal::random<int>(0,4) == 0) {
r = c; // check square matrices in 25% of tries
}
EIGEN_UNUSED_VARIABLE(r+c);
CALL_SUBTEST_1(( sparse_vector<double,int>(8, 8) ));
CALL_SUBTEST_2(( sparse_vector<std::complex<double>, int>(16, 16) ));
CALL_SUBTEST_1(( sparse_vector<double,long int>(299, 535) ));
CALL_SUBTEST_1(( sparse_vector<double,short>(299, 535) ));
CALL_SUBTEST_2(( sparse_vector<std::complex<double>, int>(r, c) ));
CALL_SUBTEST_1(( sparse_vector<double,long int>(r, c) ));
CALL_SUBTEST_1(( sparse_vector<double,short>(r, c) ));
}
}

View File

@@ -163,6 +163,21 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
VERIFY(!(numext::isfinite)(v.blueNorm())); VERIFY((numext::isnan)(v.blueNorm()));
VERIFY(!(numext::isfinite)(v.hypotNorm())); VERIFY((numext::isnan)(v.hypotNorm()));
}
// stableNormalize[d]
{
VERIFY_IS_APPROX(vrand.stableNormalized(), vrand.normalized());
MatrixType vcopy(vrand);
vcopy.stableNormalize();
VERIFY_IS_APPROX(vcopy, vrand.normalized());
VERIFY_IS_APPROX((vrand.stableNormalized()).norm(), RealScalar(1));
VERIFY_IS_APPROX(vcopy.norm(), RealScalar(1));
VERIFY_IS_APPROX((vbig.stableNormalized()).norm(), RealScalar(1));
VERIFY_IS_APPROX((vsmall.stableNormalized()).norm(), RealScalar(1));
RealScalar big_scaling = ((std::numeric_limits<RealScalar>::max)() * RealScalar(1e-4));
VERIFY_IS_APPROX(vbig/big_scaling, (vbig.stableNorm() * vbig.stableNormalized()).eval()/big_scaling);
VERIFY_IS_APPROX(vsmall, vsmall.stableNorm() * vsmall.stableNormalized());
}
}
void test_stable_norm()

158
test/stddeque_overload.cpp Normal file
View File

@@ -0,0 +1,158 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "main.h"
#include <Eigen/StdDeque>
#include <Eigen/Geometry>
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Vector4f)
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix2f)
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix4f)
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Matrix4d)
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Affine3f)
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Affine3d)
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Quaternionf)
EIGEN_DEFINE_STL_DEQUE_SPECIALIZATION(Quaterniond)
template<typename MatrixType>
void check_stddeque_matrix(const MatrixType& m)
{
typename MatrixType::Index rows = m.rows();
typename MatrixType::Index cols = m.cols();
MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
std::deque<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
v[5] = x;
w[6] = v[5];
VERIFY_IS_APPROX(w[6], v[5]);
v = w;
for(int i = 0; i < 20; i++)
{
VERIFY_IS_APPROX(w[i], v[i]);
}
v.resize(21);
v[20] = x;
VERIFY_IS_APPROX(v[20], x);
v.resize(22,y);
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
// do a lot of push_back such that the deque gets internally resized
// (with memory reallocation)
MatrixType* ref = &w[0];
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
v.push_back(w[i%w.size()]);
for(unsigned int i=23; i<v.size(); ++i)
{
VERIFY(v[i]==w[(i-23)%w.size()]);
}
}
template<typename TransformType>
void check_stddeque_transform(const TransformType&)
{
typedef typename TransformType::MatrixType MatrixType;
TransformType x(MatrixType::Random()), y(MatrixType::Random());
std::deque<TransformType> v(10), w(20, y);
v[5] = x;
w[6] = v[5];
VERIFY_IS_APPROX(w[6], v[5]);
v = w;
for(int i = 0; i < 20; i++)
{
VERIFY_IS_APPROX(w[i], v[i]);
}
v.resize(21);
v[20] = x;
VERIFY_IS_APPROX(v[20], x);
v.resize(22,y);
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
// do a lot of push_back such that the deque gets internally resized
// (with memory reallocation)
TransformType* ref = &w[0];
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
v.push_back(w[i%w.size()]);
for(unsigned int i=23; i<v.size(); ++i)
{
VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
}
}
template<typename QuaternionType>
void check_stddeque_quaternion(const QuaternionType&)
{
typedef typename QuaternionType::Coefficients Coefficients;
QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
std::deque<QuaternionType> v(10), w(20, y);
v[5] = x;
w[6] = v[5];
VERIFY_IS_APPROX(w[6], v[5]);
v = w;
for(int i = 0; i < 20; i++)
{
VERIFY_IS_APPROX(w[i], v[i]);
}
v.resize(21);
v[20] = x;
VERIFY_IS_APPROX(v[20], x);
v.resize(22,y);
VERIFY_IS_APPROX(v[21], y);
v.push_back(x);
VERIFY_IS_APPROX(v[22], x);
// do a lot of push_back such that the deque gets internally resized
// (with memory reallocation)
QuaternionType* ref = &w[0];
for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
v.push_back(w[i%w.size()]);
for(unsigned int i=23; i<v.size(); ++i)
{
VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
}
}
void test_stddeque_overload()
{
// some non vectorizable fixed sizes
CALL_SUBTEST_1(check_stddeque_matrix(Vector2f()));
CALL_SUBTEST_1(check_stddeque_matrix(Matrix3f()));
CALL_SUBTEST_2(check_stddeque_matrix(Matrix3d()));
// some vectorizable fixed sizes
CALL_SUBTEST_1(check_stddeque_matrix(Matrix2f()));
CALL_SUBTEST_1(check_stddeque_matrix(Vector4f()));
CALL_SUBTEST_1(check_stddeque_matrix(Matrix4f()));
CALL_SUBTEST_2(check_stddeque_matrix(Matrix4d()));
// some dynamic sizes
CALL_SUBTEST_3(check_stddeque_matrix(MatrixXd(1,1)));
CALL_SUBTEST_3(check_stddeque_matrix(VectorXd(20)));
CALL_SUBTEST_3(check_stddeque_matrix(RowVectorXf(20)));
CALL_SUBTEST_3(check_stddeque_matrix(MatrixXcf(10,10)));
// some Transform
CALL_SUBTEST_4(check_stddeque_transform(Affine2f())); // does not need the specialization (2+1)^2 = 9
CALL_SUBTEST_4(check_stddeque_transform(Affine3f()));
CALL_SUBTEST_4(check_stddeque_transform(Affine3d()));
// some Quaternion
CALL_SUBTEST_5(check_stddeque_quaternion(Quaternionf()));
CALL_SUBTEST_5(check_stddeque_quaternion(Quaterniond()));
}

192
test/stdlist_overload.cpp Normal file
View File

@@ -0,0 +1,192 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "main.h"
#include <Eigen/StdList>
#include <Eigen/Geometry>
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Vector4f)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix2f)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix4f)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix4d)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Affine3f)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Affine3d)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Quaternionf)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Quaterniond)
template <class Container, class Position>
typename Container::iterator get(Container & c, Position position)
{
typename Container::iterator it = c.begin();
std::advance(it, position);
return it;
}
template <class Container, class Position, class Value>
void set(Container & c, Position position, const Value & value)
{
typename Container::iterator it = c.begin();
std::advance(it, position);
*it = value;
}
template<typename MatrixType>
void check_stdlist_matrix(const MatrixType& m)
{
typename MatrixType::Index rows = m.rows();
typename MatrixType::Index cols = m.cols();
MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
std::list<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
typename std::list<MatrixType>::iterator itv = get(v, 5);
typename std::list<MatrixType>::iterator itw = get(w, 6);
*itv = x;
*itw = *itv;
VERIFY_IS_APPROX(*itw, *itv);
v = w;
itv = v.begin();
itw = w.begin();
for(int i = 0; i < 20; i++)
{
VERIFY_IS_APPROX(*itw, *itv);
++itv;
++itw;
}
v.resize(21);
set(v, 20, x);
VERIFY_IS_APPROX(*get(v, 20), x);
v.resize(22,y);
VERIFY_IS_APPROX(*get(v, 21), y);
v.push_back(x);
VERIFY_IS_APPROX(*get(v, 22), x);
// do a lot of push_back such that the list gets internally resized
// (with memory reallocation)
MatrixType* ref = &(*get(w, 0));
for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
v.push_back(*get(w, i%w.size()));
for(unsigned int i=23; i<v.size(); ++i)
{
VERIFY((*get(v, i))==(*get(w, (i-23)%w.size())));
}
}
template<typename TransformType>
void check_stdlist_transform(const TransformType&)
{
typedef typename TransformType::MatrixType MatrixType;
TransformType x(MatrixType::Random()), y(MatrixType::Random());
std::list<TransformType> v(10), w(20, y);
typename std::list<TransformType>::iterator itv = get(v, 5);
typename std::list<TransformType>::iterator itw = get(w, 6);
*itv = x;
*itw = *itv;
VERIFY_IS_APPROX(*itw, *itv);
v = w;
itv = v.begin();
itw = w.begin();
for(int i = 0; i < 20; i++)
{
VERIFY_IS_APPROX(*itw, *itv);
++itv;
++itw;
}
v.resize(21);
set(v, 20, x);
VERIFY_IS_APPROX(*get(v, 20), x);
v.resize(22,y);
VERIFY_IS_APPROX(*get(v, 21), y);
v.push_back(x);
VERIFY_IS_APPROX(*get(v, 22), x);
// do a lot of push_back such that the list gets internally resized
// (with memory reallocation)
TransformType* ref = &(*get(w, 0));
for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
v.push_back(*get(w, i%w.size()));
for(unsigned int i=23; i<v.size(); ++i)
{
VERIFY(get(v, i)->matrix()==get(w, (i-23)%w.size())->matrix());
}
}
template<typename QuaternionType>
void check_stdlist_quaternion(const QuaternionType&)
{
typedef typename QuaternionType::Coefficients Coefficients;
QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
std::list<QuaternionType> v(10), w(20, y);
typename std::list<QuaternionType>::iterator itv = get(v, 5);
typename std::list<QuaternionType>::iterator itw = get(w, 6);
*itv = x;
*itw = *itv;
VERIFY_IS_APPROX(*itw, *itv);
v = w;
itv = v.begin();
itw = w.begin();
for(int i = 0; i < 20; i++)
{
VERIFY_IS_APPROX(*itw, *itv);
++itv;
++itw;
}
v.resize(21);
set(v, 20, x);
VERIFY_IS_APPROX(*get(v, 20), x);
v.resize(22,y);
VERIFY_IS_APPROX(*get(v, 21), y);
v.push_back(x);
VERIFY_IS_APPROX(*get(v, 22), x);
// do a lot of push_back such that the list gets internally resized
// (with memory reallocation)
QuaternionType* ref = &(*get(w, 0));
for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
v.push_back(*get(w, i%w.size()));
for(unsigned int i=23; i<v.size(); ++i)
{
VERIFY(get(v, i)->coeffs()==get(w, (i-23)%w.size())->coeffs());
}
}
void test_stdlist_overload()
{
// some non vectorizable fixed sizes
CALL_SUBTEST_1(check_stdlist_matrix(Vector2f()));
CALL_SUBTEST_1(check_stdlist_matrix(Matrix3f()));
CALL_SUBTEST_2(check_stdlist_matrix(Matrix3d()));
// some vectorizable fixed sizes
CALL_SUBTEST_1(check_stdlist_matrix(Matrix2f()));
CALL_SUBTEST_1(check_stdlist_matrix(Vector4f()));
CALL_SUBTEST_1(check_stdlist_matrix(Matrix4f()));
CALL_SUBTEST_2(check_stdlist_matrix(Matrix4d()));
// some dynamic sizes
CALL_SUBTEST_3(check_stdlist_matrix(MatrixXd(1,1)));
CALL_SUBTEST_3(check_stdlist_matrix(VectorXd(20)));
CALL_SUBTEST_3(check_stdlist_matrix(RowVectorXf(20)));
CALL_SUBTEST_3(check_stdlist_matrix(MatrixXcf(10,10)));
// some Transform
CALL_SUBTEST_4(check_stdlist_transform(Affine2f())); // does not need the specialization (2+1)^2 = 9
CALL_SUBTEST_4(check_stdlist_transform(Affine3f()));
CALL_SUBTEST_4(check_stdlist_transform(Affine3d()));
// some Quaternion
CALL_SUBTEST_5(check_stdlist_quaternion(Quaternionf()));
CALL_SUBTEST_5(check_stdlist_quaternion(Quaterniond()));
}

View File

@@ -1,12 +1,15 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
#undef EIGEN_DEFAULT_TO_ROW_MAJOR
#endif
#define EIGEN_DEBUG_ASSIGN
#include "main.h"
#include <typeinfo>

View File

@@ -210,6 +210,9 @@ template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
VERIFY_IS_APPROX(m1.cwiseAbs().colwise().maxCoeff(), m1.colwise().template lpNorm<Infinity>());
VERIFY_IS_APPROX(m1.cwiseAbs().rowwise().maxCoeff(), m1.rowwise().template lpNorm<Infinity>());
// regression for bug 1158
VERIFY_IS_APPROX(m1.cwiseAbs().colwise().sum().x(), m1.col(0).cwiseAbs().sum());
// test normalized
m2 = m1.colwise().normalized();
VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());

View File

@@ -25,6 +25,7 @@ template<typename MatrixType> void zeroReduction(const MatrixType& m) {
template<typename MatrixType> void zeroSizedMatrix()
{
MatrixType t1;
typedef typename MatrixType::Scalar Scalar;
if (MatrixType::SizeAtCompileTime == Dynamic || MatrixType::SizeAtCompileTime == 0)
{
@@ -37,7 +38,7 @@ template<typename MatrixType> void zeroSizedMatrix()
if (MatrixType::RowsAtCompileTime == Dynamic && MatrixType::ColsAtCompileTime == Dynamic)
{
MatrixType t2(0, 0);
MatrixType t2(0, 0), t3(t1);
VERIFY(t2.rows() == 0);
VERIFY(t2.cols() == 0);
@@ -45,6 +46,23 @@ template<typename MatrixType> void zeroSizedMatrix()
VERIFY(t1==t2);
}
}
if(MatrixType::MaxColsAtCompileTime!=0 && MatrixType::MaxRowsAtCompileTime!=0)
{
Index rows = MatrixType::RowsAtCompileTime==Dynamic ? internal::random<Index>(1,10) : Index(MatrixType::RowsAtCompileTime);
Index cols = MatrixType::ColsAtCompileTime==Dynamic ? internal::random<Index>(1,10) : Index(MatrixType::ColsAtCompileTime);
MatrixType m(rows,cols);
zeroReduction(m.template block<0,MatrixType::ColsAtCompileTime>(0,0,0,cols));
zeroReduction(m.template block<MatrixType::RowsAtCompileTime,0>(0,0,rows,0));
zeroReduction(m.template block<0,1>(0,0));
zeroReduction(m.template block<1,0>(0,0));
Matrix<Scalar,Dynamic,Dynamic> prod = m.template block<MatrixType::RowsAtCompileTime,0>(0,0,rows,0) * m.template block<0,MatrixType::ColsAtCompileTime>(0,0,0,cols);
VERIFY(prod.rows()==rows && prod.cols()==cols);
VERIFY(prod.isZero());
prod = m.template block<1,0>(0,0) * m.template block<0,1>(0,0);
VERIFY(prod.size()==1);
VERIFY(prod.isZero());
}
}
template<typename VectorType> void zeroSizedVector()