merge my Dynamic -> -1 change

This commit is contained in:
Benoit Jacob
2010-06-11 08:04:06 -04:00
129 changed files with 2395 additions and 1237 deletions

View File

@@ -129,7 +129,7 @@ template<typename ArrayType> void comparisons(const ArrayType& m)
VERIFY(((m1.abs()+1)>RealScalar(0.1)).count() == rows*cols);
typedef Array<typename ArrayType::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));
@@ -151,10 +151,10 @@ template<typename ArrayType> void array_real(const ArrayType& m)
VERIFY_IS_APPROX(m1.sin(), ei_sin(m1));
VERIFY_IS_APPROX(m1.cos(), std::cos(m1));
VERIFY_IS_APPROX(m1.cos(), ei_cos(m1));
VERIFY_IS_APPROX(ei_cos(m1+RealScalar(3)*m2), ei_cos((m1+RealScalar(3)*m2).eval()));
VERIFY_IS_APPROX(std::cos(m1+RealScalar(3)*m2), std::cos((m1+RealScalar(3)*m2).eval()));
VERIFY_IS_APPROX(m1.abs().sqrt(), std::sqrt(std::abs(m1)));
VERIFY_IS_APPROX(m1.abs().sqrt(), ei_sqrt(ei_abs(m1)));
VERIFY_IS_APPROX(m1.abs(), ei_sqrt(ei_abs2(m1)));
@@ -163,10 +163,10 @@ template<typename ArrayType> void array_real(const ArrayType& m)
VERIFY_IS_APPROX(ei_abs2(std::real(m1)) + ei_abs2(std::imag(m1)), ei_abs2(m1));
if(!NumTraits<Scalar>::IsComplex)
VERIFY_IS_APPROX(ei_real(m1), m1);
VERIFY_IS_APPROX(m1.abs().log(), std::log(std::abs(m1)));
VERIFY_IS_APPROX(m1.abs().log(), ei_log(ei_abs(m1)));
VERIFY_IS_APPROX(m1.exp(), std::exp(m1));
VERIFY_IS_APPROX(m1.exp() * m2.exp(), std::exp(m1+m2));
VERIFY_IS_APPROX(m1.exp(), ei_exp(m1));

View File

@@ -37,10 +37,10 @@ template<typename MatrixType> void array_for_matrix(const MatrixType& m)
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 = ei_random<Scalar>(),
s2 = ei_random<Scalar>();

View File

@@ -103,47 +103,6 @@ template<typename MatrixType> void reverse(const MatrixType& m)
}
}
/*
cout << "m1:" << endl << m1 << endl;
cout << "m1c_reversed:" << endl << m1c_reversed << endl;
cout << "----------------" << endl;
for ( int i=0; i< rows*cols; i++){
cout << m1c_reversed.coeff(i) << endl;
}
cout << "----------------" << endl;
for ( int i=0; i< rows*cols; i++){
cout << m1c_reversed.colwise().reverse().coeff(i) << endl;
}
cout << "================" << endl;
cout << "m1.coeff( ind ): " << m1.coeff( ind ) << endl;
cout << "m1c_reversed.colwise().reverse().coeff( ind ): " << m1c_reversed.colwise().reverse().coeff( ind ) << endl;
*/
//MatrixType m1r_reversed = m1.rowwise().reverse();
//VERIFY_IS_APPROX( m1r_reversed.rowwise().reverse().coeff( ind ), m1.coeff( ind ) );
/*
cout << "m1" << endl << m1 << endl;
cout << "m1 using coeff(int index)" << endl;
for ( int i = 0; i < rows*cols; i++) {
cout << m1.coeff(i) << " ";
}
cout << endl;
cout << "m1.transpose()" << endl << m1.transpose() << endl;
cout << "m1.transpose() using coeff(int index)" << endl;
for ( int i = 0; i < rows*cols; i++) {
cout << m1.transpose().coeff(i) << " ";
}
cout << endl;
*/
/*
Scalar x = ei_random<Scalar>();
int r = ei_random<int>(0, rows-1),
@@ -152,6 +111,7 @@ template<typename MatrixType> void reverse(const MatrixType& m)
m1.reverse()(r, c) = x;
VERIFY_IS_APPROX(x, m1(rows - 1 - r, cols - 1 - c));
/*
m1.colwise().reverse()(r, c) = x;
VERIFY_IS_APPROX(x, m1(rows - 1 - r, c));

View File

@@ -138,7 +138,8 @@ template<typename MatrixType> void basicStuffComplex(const MatrixType& m)
VERIFY(ei_imag(s1)==ei_imag_ref(s1));
ei_real_ref(s1) = ei_real(s2);
ei_imag_ref(s1) = ei_imag(s2);
VERIFY(s1==s2);
VERIFY(ei_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);

View File

@@ -26,10 +26,21 @@
#define EIGEN_NO_ASSERTION_CHECKING
#endif
static int nb_temporaries;
#define EIGEN_DEBUG_MATRIX_CTOR { if(size!=0) nb_temporaries++; }
#include "main.h"
#include <Eigen/Cholesky>
#include <Eigen/QR>
#define VERIFY_EVALUATION_COUNT(XPR,N) {\
nb_temporaries = 0; \
XPR; \
if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
VERIFY( (#XPR) && nb_temporaries==N ); \
}
#ifdef HAS_GSL
#include "gsl_helper.h"
#endif
@@ -110,20 +121,46 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
VERIFY_IS_APPROX(symm * matX, matB);
}
int sign = ei_random<int>()%2 ? 1 : -1;
if(sign == -1)
// LDLT
{
symm = -symm; // test a negative matrix
}
int sign = ei_random<int>()%2 ? 1 : -1;
{
LDLT<SquareMatrixType> ldlt(symm);
VERIFY_IS_APPROX(symm, ldlt.reconstructedMatrix());
vecX = ldlt.solve(vecB);
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_IS_APPROX(symm, ldltlo.reconstructedMatrix());
vecX = ldltlo.solve(vecB);
VERIFY_IS_APPROX(symm * vecX, vecB);
matX = ldlt.solve(matB);
matX = ldltlo.solve(matB);
VERIFY_IS_APPROX(symm * matX, matB);
LDLT<SquareMatrixType,Upper> ldltup(symmUp);
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);
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());
}
}
}
@@ -134,6 +171,7 @@ template<typename MatrixType> void cholesky_verify_assert()
LLT<MatrixType> llt;
VERIFY_RAISES_ASSERT(llt.matrixL())
VERIFY_RAISES_ASSERT(llt.matrixU())
VERIFY_RAISES_ASSERT(llt.solve(tmp))
VERIFY_RAISES_ASSERT(llt.solveInPlace(&tmp))

View File

@@ -2,6 +2,7 @@
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -23,6 +24,7 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
#include <Eigen/LU>
@@ -31,12 +33,14 @@
template<typename VectorType>
void verify_is_approx_upto_permutation(const VectorType& vec1, const VectorType& vec2)
{
typedef typename NumTraits<typename VectorType::Scalar>::Real RealScalar;
VERIFY(vec1.cols() == 1);
VERIFY(vec2.cols() == 1);
VERIFY(vec1.rows() == vec2.rows());
for (int k = 1; k <= vec1.rows(); ++k)
{
VERIFY_IS_APPROX(vec1.array().pow(k).sum(), vec2.array().pow(k).sum());
VERIFY_IS_APPROX(vec1.array().pow(RealScalar(k)).sum(), vec2.array().pow(RealScalar(k)).sum());
}
}
@@ -59,14 +63,20 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
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> 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);
@@ -74,6 +84,25 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
MatrixType id = MatrixType::Identity(rows, cols);
VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));
if (rows > 1)
{
// 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);
}
}
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());
}
void test_eigensolver_complex()
@@ -85,6 +114,11 @@ void test_eigensolver_complex()
CALL_SUBTEST_4( eigensolver(Matrix3f()) );
}
CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4cf()) );
CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXcd(14,14)) );
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>(10));
}

View File

@@ -2,6 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -23,6 +24,7 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
#ifdef HAS_GSL
@@ -43,36 +45,52 @@ template<typename MatrixType> void eigensolver(const MatrixType& m)
typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
// RealScalar largerEps = 10*test_precision<RealScalar>();
MatrixType a = MatrixType::Random(rows,cols);
MatrixType a1 = MatrixType::Random(rows,cols);
MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
EigenSolver<MatrixType> ei0(symmA);
VERIFY_IS_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);
VERIFY_IS_EQUAL(ei1.info(), Success);
VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
VERIFY_IS_APPROX(a.eigenvalues(), ei1.eigenvalues());
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)
{
// Test matrix with NaN
a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
EigenSolver<MatrixType> eiNaN(a);
VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
}
}
template<typename MatrixType> void eigensolver_verify_assert()
template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
{
MatrixType tmp;
EigenSolver<MatrixType> eig;
VERIFY_RAISES_ASSERT(eig.eigenvectors())
VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors())
VERIFY_RAISES_ASSERT(eig.pseudoEigenvalueMatrix())
VERIFY_RAISES_ASSERT(eig.eigenvalues())
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());
}
void test_eigensolver_generic()
@@ -88,11 +106,11 @@ void test_eigensolver_generic()
CALL_SUBTEST_4( eigensolver(Matrix2d()) );
}
CALL_SUBTEST_1( eigensolver_verify_assert<Matrix4f>() );
CALL_SUBTEST_2( eigensolver_verify_assert<MatrixXd>() );
CALL_SUBTEST_4( eigensolver_verify_assert<Matrix2d>() );
CALL_SUBTEST_5( eigensolver_verify_assert<MatrixXf>() );
CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4f()) );
CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXd(17,17)) );
CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<double,1,1>()) );
CALL_SUBTEST_4( eigensolver_verify_assert(Matrix2d()) );
// Test problem size constructors
CALL_SUBTEST_6(EigenSolver<MatrixXf>(10));
CALL_SUBTEST_5(EigenSolver<MatrixXf>(10));
}

View File

@@ -2,6 +2,7 @@
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -23,6 +24,7 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
#ifdef HAS_GSL
@@ -48,10 +50,12 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
MatrixType a = MatrixType::Random(rows,cols);
MatrixType a1 = MatrixType::Random(rows,cols);
MatrixType symmA = a.adjoint() * a + a1.adjoint() * a1;
symmA.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();
SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
// generalized eigen pb
@@ -60,6 +64,9 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
#ifdef HAS_GSL
if (ei_is_same_type<RealScalar,double>::ret)
{
// restore symmA and symmB.
symmA = MatrixType(symmA.template selfadjointView<Lower>());
symmB = MatrixType(symmB.template selfadjointView<Lower>());
typedef GslTraits<Scalar> Gsl;
typename Gsl::Matrix gEvec=0, gSymmA=0, gSymmB=0;
typename GslTraits<RealScalar>::Vector gEval=0;
@@ -89,10 +96,9 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal()), largerEps));
// compare with eigen
// std::cerr << _eval.transpose() << "\n" << eiSymmGen.eigenvalues().transpose() << "\n\n";
// std::cerr << _evec.format(6) << "\n\n" << eiSymmGen.eigenvectors().format(6) << "\n\n\n";
MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse();
VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues());
VERIFY_IS_APPROX(_evec.cwiseAbs(), eiSymmGen.eigenvectors().cwiseAbs());
VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs());
Gsl::free(gSymmA);
Gsl::free(gSymmB);
@@ -101,20 +107,46 @@ template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
}
#endif
VERIFY((symmA * eiSymm.eigenvectors()).isApprox(
VERIFY_IS_EQUAL(eiSymm.info(), Success);
VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox(
eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues());
SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false);
VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success);
VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues());
// generalized eigen problem Ax = lBx
VERIFY((symmA * eiSymmGen.eigenvectors()).isApprox(
symmB * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
VERIFY((symmA.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox(
symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
MatrixType sqrtSymmA = eiSymm.operatorSqrt();
VERIFY_IS_APPROX(symmA, sqrtSymmA*sqrtSymmA);
VERIFY_IS_APPROX(sqrtSymmA, symmA*eiSymm.operatorInverseSqrt());
VERIFY_IS_APPROX(MatrixType(symmA.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA);
VERIFY_IS_APPROX(sqrtSymmA, symmA.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());
if (rows > 1)
{
// Test matrix with NaN
symmA(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmA);
VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence);
}
}
void test_eigensolver_selfadjoint()

View File

@@ -34,6 +34,8 @@ void test_first_aligned_helper(Scalar *array, int size)
template<typename Scalar>
void test_none_aligned_helper(Scalar *array, int size)
{
EIGEN_UNUSED_VARIABLE(array);
EIGEN_UNUSED_VARIABLE(size);
VERIFY(ei_packet_traits<Scalar>::size == 1 || ei_first_aligned(array, size) == size);
}

View File

@@ -54,6 +54,13 @@ template<typename Scalar,int Size> void hessenberg(int size = Size)
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()
}

View File

@@ -31,7 +31,37 @@
#undef VERIFY_IS_NOT_APPROX
#define VERIFY_IS_NOT_APPROX(a, b) VERIFY((a)!=(b));
template<typename MatrixType> void integer_types(const MatrixType& m)
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);
int rows = m.rows();
int 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 = ei_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;
@@ -97,13 +127,10 @@ template<typename MatrixType> void integer_types(const MatrixType& m)
s1 = ei_random<Scalar>();
} while(s1 == 0);
VERIFY_IS_EQUAL(-(-m1), m1);
VERIFY_IS_EQUAL(m1+m1, 2*m1);
VERIFY_IS_EQUAL(m1+m2-m1, m2);
VERIFY_IS_EQUAL(-m2+m1+m2, m1);
VERIFY_IS_EQUAL(m1*s1, s1*m1);
VERIFY_IS_EQUAL((m1+m2)*s1, s1*m1+s1*m2);
VERIFY_IS_EQUAL((-m1+m2)*s1, -s1*m1+s1*m2);
m3 = m2; m3 += m1;
VERIFY_IS_EQUAL(m3, m1+m2);
m3 = m2; m3 -= m1;
@@ -122,18 +149,26 @@ template<typename MatrixType> void integer_types(const MatrixType& m)
void test_integer_types()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( integer_types(Matrix<unsigned int, 1, 1>()) );
CALL_SUBTEST_1( integer_types(Matrix<unsigned long, 3, 4>()) );
CALL_SUBTEST_2( integer_types(Matrix<long, 2, 2>()) );
CALL_SUBTEST_1( integer_type_tests(Matrix<unsigned int, 1, 1>()) );
CALL_SUBTEST_1( integer_type_tests(Matrix<unsigned long, 3, 4>()) );
CALL_SUBTEST_3( integer_types(Matrix<char, 2, Dynamic>(2, 10)) );
CALL_SUBTEST_4( integer_types(Matrix<unsigned char, 3, 3>()) );
CALL_SUBTEST_4( integer_types(Matrix<unsigned char, Dynamic, Dynamic>(20, 20)) );
CALL_SUBTEST_2( integer_type_tests(Matrix<long, 2, 2>()) );
CALL_SUBTEST_2( signed_integer_type_tests(Matrix<long, 2, 2>()) );
CALL_SUBTEST_5( integer_types(Matrix<short, Dynamic, 4>(7, 4)) );
CALL_SUBTEST_6( integer_types(Matrix<unsigned short, 4, 4>()) );
CALL_SUBTEST_3( integer_type_tests(Matrix<char, 2, Dynamic>(2, 10)) );
CALL_SUBTEST_3( signed_integer_type_tests(Matrix<char, 2, Dynamic>(2, 10)) );
CALL_SUBTEST_7( integer_types(Matrix<long long, 11, 13>()) );
CALL_SUBTEST_8( integer_types(Matrix<unsigned long long, Dynamic, 5>(1, 5)) );
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>()) );
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)) );
}
}

View File

@@ -78,10 +78,23 @@ template<typename MatrixType> void inverse(const MatrixType& m)
MatrixType m3 = v3*v3.transpose(), m4(rows,cols);
m3.computeInverseAndDetWithCheck(m4, det, invertible);
VERIFY( rows==1 ? invertible : !invertible );
VERIFY_IS_APPROX(det, m3.determinant());
VERIFY_IS_MUCH_SMALLER_THAN(ei_abs(det-m3.determinant()), RealScalar(1));
m3.computeInverseWithCheck(m4, invertible);
VERIFY( rows==1 ? invertible : !invertible );
#endif
// 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);
}
}
void test_inverse()

View File

@@ -120,7 +120,7 @@ template<typename MatrixType> void lu_invertible()
MatrixType m1(size, size), m2(size, size), m3(size, size);
FullPivLU<MatrixType> lu;
lu.setThreshold(0.01);
lu.setThreshold(RealScalar(0.01));
do {
m1 = MatrixType::Random(size,size);
lu.compute(m1);

View File

@@ -368,7 +368,7 @@ inline bool test_isUnitary(const MatrixBase<Derived>& m)
}
template<typename T, typename U>
bool test_is_equal(T actual, U expected)
bool test_is_equal(const T& actual, const U& expected)
{
if (actual==expected)
return true;

View File

@@ -51,8 +51,8 @@ void testVectorType(const VectorType& base)
{
typedef typename ei_traits<VectorType>::Scalar Scalar;
Scalar low = ei_random<Scalar>(-500,500);
Scalar high = ei_random<Scalar>(-500,500);
if (low>high) std::swap(low,high);
Scalar high = ei_random<Scalar>(-500,500);
if (low>high) std::swap(low,high);
const int size = base.size();
const Scalar step = (high-low)/(size-1);
@@ -91,7 +91,7 @@ void testVectorType(const VectorType& base)
Matrix<Scalar,Dynamic,1> size_changer(size+50);
size_changer.setLinSpaced(low,high,size);
VERIFY( size_changer.size() == size );
VERIFY( size_changer.size() == size );
}
template<typename MatrixType>

View File

@@ -64,9 +64,7 @@ template<typename MatrixType> void inverse_general_4x4(int repeat)
double error_avg = error_sum / repeat;
EIGEN_DEBUG_VAR(error_avg);
EIGEN_DEBUG_VAR(error_max);
// FIXME that 1.3 used to be a 1.0 until the NumTraits changes on 28 April 2010, and then a 1.2 until the ReturnByValue/Inverse changes
// on 30 May 2010, what's going wrong (if anything) ??
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.3));
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.2)); // FIXME that 1.2 used to be a 1.0 until the NumTraits changes on 28 April 2010, what's going wrong??
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
}

View File

@@ -71,8 +71,9 @@ template<typename MatrixType> void product(const MatrixType& m)
Scalar s1 = ei_random<Scalar>();
int r = ei_random<int>(0, rows-1),
c = ei_random<int>(0, cols-1);
int r = ei_random<int>(0, rows-1),
c = ei_random<int>(0, cols-1),
c2 = ei_random<int>(0, cols-1);
// begin testing Product.h: only associativity for now
// (we use Transpose.h but this doesn't count as a test for it)
@@ -150,4 +151,8 @@ template<typename MatrixType> void product(const MatrixType& m)
{
VERIFY(areNotApprox(res2,square2 + m2.transpose() * m1));
}
// inner product
Scalar x = square2.row(c) * square2.col(c2);
VERIFY_IS_APPROX(x, square2.row(c).transpose().cwiseProduct(square2.col(c2)).sum());
}

View File

@@ -49,5 +49,22 @@ void test_product_large()
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 = ei_random<int>(10000,20000);
std::ptrdiff_t l2 = ei_random<int>(1000000,2000000);
setCpuCacheSizes(l1,l2);
VERIFY(l1==l1CacheSize());
VERIFY(l2==l2CacheSize());
std::ptrdiff_t k1 = ei_random<int>(10,100)*16;
std::ptrdiff_t m1 = ei_random<int>(10,100)*16;
std::ptrdiff_t n1 = ei_random<int>(10,100)*16;
setBlockingSizes<float>(k1,m1,n1);
std::ptrdiff_t k, m, n;
getBlockingSizes<float>(k,m,n);
VERIFY(k==k1 && m==m1 && n==n1);
}
#endif
}

View File

@@ -23,6 +23,7 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTime)
@@ -34,6 +35,7 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
for(int counter = 0; counter < g_repeat; ++counter) {
MatrixType A = MatrixType::Random(size, size);
ComplexSchur<MatrixType> schurOfA(A);
VERIFY_IS_EQUAL(schurOfA.info(), Success);
ComplexMatrixType U = schurOfA.matrixU();
ComplexMatrixType T = schurOfA.matrixT();
for(int row = 1; row < size; ++row) {
@@ -48,14 +50,31 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
ComplexSchur<MatrixType> csUninitialized;
VERIFY_RAISES_ASSERT(csUninitialized.matrixT());
VERIFY_RAISES_ASSERT(csUninitialized.matrixU());
VERIFY_RAISES_ASSERT(csUninitialized.info());
// Test whether compute() and constructor returns same result
MatrixType A = MatrixType::Random(size, size);
ComplexSchur<MatrixType> cs1;
cs1.compute(A);
ComplexSchur<MatrixType> cs2(A);
VERIFY_IS_EQUAL(cs1.info(), Success);
VERIFY_IS_EQUAL(cs2.info(), Success);
VERIFY_IS_EQUAL(cs1.matrixT(), cs2.matrixT());
VERIFY_IS_EQUAL(cs1.matrixU(), cs2.matrixU());
// Test computation of only T, not U
ComplexSchur<MatrixType> csOnlyT(A, false);
VERIFY_IS_EQUAL(csOnlyT.info(), Success);
VERIFY_IS_EQUAL(cs1.matrixT(), csOnlyT.matrixT());
VERIFY_RAISES_ASSERT(csOnlyT.matrixU());
if (size > 1)
{
// Test matrix with NaN
A(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
ComplexSchur<MatrixType> csNaN(A);
VERIFY_IS_EQUAL(csNaN.info(), NoConvergence);
}
}
void test_schur_complex()

View File

@@ -23,6 +23,7 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <limits>
#include <Eigen/Eigenvalues>
template<typename MatrixType> void verifyIsQuasiTriangular(const MatrixType& T)
@@ -55,6 +56,7 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
for(int counter = 0; counter < g_repeat; ++counter) {
MatrixType A = MatrixType::Random(size, size);
RealSchur<MatrixType> schurOfA(A);
VERIFY_IS_EQUAL(schurOfA.info(), Success);
MatrixType U = schurOfA.matrixU();
MatrixType T = schurOfA.matrixT();
verifyIsQuasiTriangular(T);
@@ -65,14 +67,31 @@ template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTim
RealSchur<MatrixType> rsUninitialized;
VERIFY_RAISES_ASSERT(rsUninitialized.matrixT());
VERIFY_RAISES_ASSERT(rsUninitialized.matrixU());
VERIFY_RAISES_ASSERT(rsUninitialized.info());
// Test whether compute() and constructor returns same result
MatrixType A = MatrixType::Random(size, size);
RealSchur<MatrixType> rs1;
rs1.compute(A);
RealSchur<MatrixType> rs2(A);
VERIFY_IS_EQUAL(rs1.info(), Success);
VERIFY_IS_EQUAL(rs2.info(), Success);
VERIFY_IS_EQUAL(rs1.matrixT(), rs2.matrixT());
VERIFY_IS_EQUAL(rs1.matrixU(), rs2.matrixU());
// Test computation of only T, not U
RealSchur<MatrixType> rsOnlyT(A, false);
VERIFY_IS_EQUAL(rsOnlyT.info(), Success);
VERIFY_IS_EQUAL(rs1.matrixT(), rsOnlyT.matrixT());
VERIFY_RAISES_ASSERT(rsOnlyT.matrixU());
if (size > 1)
{
// Test matrix with NaN
A(0,0) = std::numeric_limits<typename MatrixType::Scalar>::quiet_NaN();
RealSchur<MatrixType> rsNaN(A);
VERIFY_IS_EQUAL(rsNaN.info(), NoConvergence);
}
}
void test_schur_real()

View File

@@ -55,7 +55,7 @@ void test_selfadjoint()
{
for(int i = 0; i < g_repeat ; i++)
{
EIGEN_UNUSED int s = ei_random<int>(1,20);
int s = ei_random<int>(1,20); EIGEN_UNUSED_VARIABLE(s);
CALL_SUBTEST_1( selfadjoint(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( selfadjoint(Matrix<float, 2, 2>()) );

View File

@@ -81,13 +81,13 @@ initSparse(double density,
v = Scalar(0);
else if ((flags & MakeUpperTriangular) && j<i)
v = Scalar(0);
if ((flags&ForceRealDiag) && (i==j))
v = ei_real(v);
if (v!=Scalar(0))
{
sparseMat.insertBack(j,i) = v;
sparseMat.insertBackByOuterInner(j,i) = v;
if (nonzeroCoords)
nonzeroCoords->push_back(Vector2i(i,j));
}
@@ -126,13 +126,13 @@ initSparse(double density,
v = Scalar(0);
else if ((flags & MakeUpperTriangular) && j<i)
v = Scalar(0);
if ((flags&ForceRealDiag) && (i==j))
v = ei_real(v);
if (v!=Scalar(0))
{
sparseMat.insertBack(j,i) = v;
sparseMat.insertBackByOuterInner(j,i) = v;
if (nonzeroCoords)
nonzeroCoords->push_back(Vector2i(i,j));
}

View File

@@ -323,12 +323,12 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
else if (x<0.5)
{
countFalseNonZero++;
m2.insertBack(j,i) = Scalar(0);
m2.insertBackByOuterInner(j,i) = Scalar(0);
}
else
{
countTrueNonZero++;
m2.insertBack(j,i) = refM2(i,j) = Scalar(1);
m2.insertBackByOuterInner(j,i) = refM2(i,j) = Scalar(1);
}
}
}

View File

@@ -149,26 +149,27 @@ template<typename Scalar> void sparse_solvers(int rows, int cols)
}
// test LDLT
if (!NumTraits<Scalar>::IsComplex)
{
// TODO fix the issue with complex (see SparseLDLT::solveInPlace)
SparseMatrix<Scalar> m2(rows, cols);
DenseMatrix refMat2(rows, cols);
DenseVector b = DenseVector::Random(cols);
DenseVector refX(cols), x(cols);
// initSPD(density, refMat2, m2);
initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, 0, 0);
refMat2 += (refMat2.adjoint()).eval();
refMat2.diagonal() *= 0.5;
for(int i=0; i<rows; ++i)
m2.coeffRef(i,i) = refMat2(i,i) = ei_abs(ei_real(refMat2(i,i)));
refX = refMat2.llt().solve(b); // FIXME use LLT to compute the reference because LDLT seems to fail with large matrices
refX = refMat2.template selfadjointView<Upper>().llt().solve(b);
// FIXME use LLT to compute the reference because LDLT seems to fail with large matrices
typedef SparseMatrix<Scalar,Upper|SelfAdjoint> SparseSelfAdjointMatrix;
x = b;
SparseLDLT<SparseSelfAdjointMatrix> ldlt(m2);
if (ldlt.succeeded())
ldlt.solveInPlace(x);
else
std::cerr << "warning LDLT failed\n";
VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LDLT: default");
}

View File

@@ -24,6 +24,11 @@
#include "main.h"
template<typename T> bool isFinite(const T& x)
{
return x==x && x>=NumTraits<T>::lowest() && x<=NumTraits<T>::highest();
}
template<typename MatrixType> void stable_norm(const MatrixType& m)
{
/* this test covers the following files:
@@ -50,7 +55,7 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
int rows = m.rows();
int cols = m.cols();
Scalar big = ei_abs(ei_random<Scalar>()) * (std::numeric_limits<RealScalar>::max() * RealScalar(1e-4));
Scalar big = ei_random<Scalar>() * (std::numeric_limits<RealScalar>::max() * RealScalar(1e-4));
Scalar small = static_cast<RealScalar>(1)/big;
MatrixType vzero = MatrixType::Zero(rows, cols),
@@ -68,22 +73,35 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
RealScalar size = static_cast<RealScalar>(m.size());
// test overflow
/* VERIFY_IS_NOT_APPROX(static_cast<Scalar>(vbig.norm()), ei_sqrt(size)*big); // here the default norm must fail
Does not succeed on gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1, Intel Core 2 Duo T7300 with no SSE optimizations
*/
// test isFinite
VERIFY(!isFinite( std::numeric_limits<RealScalar>::infinity()));
VERIFY(!isFinite(ei_sqrt(-ei_abs(big))));
VERIFY_IS_APPROX(static_cast<Scalar>(vbig.stableNorm()), ei_sqrt(size)*big);
VERIFY_IS_APPROX(static_cast<Scalar>(vbig.blueNorm()), ei_sqrt(size)*big);
VERIFY_IS_APPROX(static_cast<Scalar>(vbig.hypotNorm()), ei_sqrt(size)*big);
// test overflow
VERIFY(isFinite(ei_sqrt(size)*ei_abs(big)));
#ifdef EIGEN_VECTORIZE_SSE
// since x87 FPU uses 80bits of precision overflow is not detected
if(ei_packet_traits<Scalar>::size>1)
{
VERIFY_IS_NOT_APPROX(static_cast<Scalar>(vbig.norm()), ei_sqrt(size)*big); // here the default norm must fail
}
#endif
VERIFY_IS_APPROX(vbig.stableNorm(), ei_sqrt(size)*ei_abs(big));
VERIFY_IS_APPROX(vbig.blueNorm(), ei_sqrt(size)*ei_abs(big));
VERIFY_IS_APPROX(vbig.hypotNorm(), ei_sqrt(size)*ei_abs(big));
// test underflow
/* VERIFY_IS_NOT_APPROX(static_cast<Scalar>(vsmall.norm()), ei_sqrt(size)*small); // here the default norm must fail
Does not succeed on gcc (Ubuntu 4.4.1-4ubuntu9) 4.4.1, Intel Core 2 Duo T7300 with no SSE optimizations
*/
VERIFY_IS_APPROX(static_cast<Scalar>(vsmall.stableNorm()), ei_sqrt(size)*small);
VERIFY_IS_APPROX(static_cast<Scalar>(vsmall.blueNorm()), ei_sqrt(size)*small);
VERIFY_IS_APPROX(static_cast<Scalar>(vsmall.hypotNorm()), ei_sqrt(size)*small);
VERIFY(isFinite(ei_sqrt(size)*ei_abs(small)));
#ifdef EIGEN_VECTORIZE_SSE
// since x87 FPU uses 80bits of precision underflow is not detected
if(ei_packet_traits<Scalar>::size>1)
{
VERIFY_IS_NOT_APPROX(static_cast<Scalar>(vsmall.norm()), ei_sqrt(size)*small); // here the default norm must fail
}
#endif
VERIFY_IS_APPROX(vsmall.stableNorm(), ei_sqrt(size)*ei_abs(small));
VERIFY_IS_APPROX(vsmall.blueNorm(), ei_sqrt(size)*ei_abs(small));
VERIFY_IS_APPROX(vsmall.hypotNorm(), ei_sqrt(size)*ei_abs(small));
// Test compilation of cwise() version
VERIFY_IS_APPROX(vrand.colwise().stableNorm(), vrand.colwise().norm());

View File

@@ -48,8 +48,13 @@ void check_stdlist_matrix(const MatrixType& m)
++wi;
}
v.resize(21);
v.resize(21);
v.back() = x;
if (!test_ei_isApprox(v.back(),x))
{
std::cout << x << std::endl;
std::cout << v.back() << std::endl;
}
VERIFY_IS_APPROX(v.back(), x);
v.resize(22,y);
VERIFY_IS_APPROX(v.back(), y);
@@ -112,6 +117,11 @@ void check_stdlist_quaternion(const QuaternionType&)
v.resize(22,y);
VERIFY_IS_APPROX(v.back(), y);
v.push_back(x);
if (!test_ei_isApprox(v.back(),x))
{
std::cout << x << std::endl;
std::cout << v.back() << std::endl;
}
VERIFY_IS_APPROX(v.back(), x);
}

View File

@@ -235,8 +235,8 @@ void test_triangular()
{
for(int i = 0; i < g_repeat ; i++)
{
EIGEN_UNUSED int r = ei_random<int>(2,20);
EIGEN_UNUSED int c = ei_random<int>(2,20);
int r = ei_random<int>(2,20); EIGEN_UNUSED_VARIABLE(r);
int c = ei_random<int>(2,20); EIGEN_UNUSED_VARIABLE(c);
CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) );
CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) );

View File

@@ -52,5 +52,8 @@ void test_unalignedcount()
VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) -= b.segment(0,40), 10, 10, 10, 0);
VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) *= 3.5, 10, 0, 10, 0);
VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) /= 3.5, 10, 0, 10, 0);
#else
// The following line is to eliminate "variable not used" warnings
nb_load = nb_loadu = nb_store = nb_storeu = 0;
#endif
}