update of the testing framework:

replaced the QTestLib framework my custom macros
and a (optional) custom script to run the tests from ctest.
This commit is contained in:
Gael Guennebaud 2008-05-22 12:18:55 +00:00
parent c6789a279c
commit 522e24f2d7
17 changed files with 393 additions and 374 deletions

View File

@ -2,43 +2,78 @@ IF(BUILD_TESTS)
OPTION(EIGEN_NO_ASSERTION_CHECKING "Disable checking of assertions" OFF)
# similar to SET_TARGET_PROPERTIES but append the property instead of overwritting it
MACRO(EI_ADD_TARGET_PROPERTY target prop value)
GET_TARGET_PROPERTY(previous ${target} ${prop})
SET_TARGET_PROPERTIES(${target} PROPERTIES ${prop} "${previous} ${value}")
ENDMACRO(EI_ADD_TARGET_PROPERTY)
# Macro to add a test
#
# the unique parameter testname must correspond to a file
# <testname>.cpp which follows this pattern:
#
# #include "main.h"
# void test_<testname>() { ... }
#
# this macro add an executable test_<testname> as well as a ctest test
# named <testname>
#
# On platforms with bash simply run:
# "ctest -V" or "ctest -V -R <testname>"
# On other platform use ctest as usual
#
MACRO(EI_ADD_TEST testname)
SET(targetname test_${testname})
ADD_EXECUTABLE(${targetname} ${testname}.cpp)
IF(NOT EIGEN_NO_ASSERTION_CHECKING)
SET_TARGET_PROPERTIES(${targetname} PROPERTIES COMPILE_FLAGS "-fexceptions")
OPTION(EIGEN_DEBUG_ASSERTS "Enable debuging of assertions" OFF)
IF(EIGEN_DEBUG_ASSERTS)
SET_TARGET_PROPERTIES(${targetname} PROPERTIES COMPILE_DEFINITIONS "-DEIGEN_DEBUG_ASSERTS=1")
ENDIF(EIGEN_DEBUG_ASSERTS)
ELSE(NOT EIGEN_NO_ASSERTION_CHECKING)
SET_TARGET_PROPERTIES(${targetname} PROPERTIES COMPILE_DEFINITIONS "-DEIGEN_NO_ASSERTION_CHECKING=1")
ENDIF(NOT EIGEN_NO_ASSERTION_CHECKING)
EI_ADD_TARGET_PROPERTY(${targetname} COMPILE_FLAGS "-DEIGEN_TEST_FUNC=${testname}")
IF(WIN32)
ADD_TEST(${testname} "${targetname}")
ELSE(WIN32)
ADD_TEST(${testname} "${CMAKE_CURRENT_SOURCE_DIR}/runtest.sh" "${testname}")
ENDIF(WIN32)
TARGET_LINK_LIBRARIES(${targetname} ${QT_QTCORE_LIBRARY} ${QT_QTTEST_LIBRARY} )
ENDMACRO(EI_ADD_TEST)
ENABLE_TESTING()
FIND_PACKAGE(Qt4 REQUIRED)
INCLUDE_DIRECTORIES( ${QT_INCLUDE_DIR} )
SET(test_SRCS
cholesky.cpp
main.cpp
basicstuff.cpp
linearstructure.cpp
product.cpp
adjoint.cpp
submatrices.cpp
miscmatrices.cpp
smallvectors.cpp
map.cpp
cwiseop.cpp
# determinant.cpp
triangular.cpp
)
QT4_AUTOMOC(${test_SRCS})
ADD_EXECUTABLE(test ${test_SRCS})
TARGET_LINK_LIBRARIES(test ${QT_QTCORE_LIBRARY} ${QT_QTTEST_LIBRARY})
IF(NOT EIGEN_NO_ASSERTION_CHECKING)
SET_TARGET_PROPERTIES(test PROPERTIES COMPILE_FLAGS "-fexceptions")
OPTION(EIGEN_DEBUG_ASSERTS "Enable debuging of assertions" OFF)
IF(EIGEN_DEBUG_ASSERTS)
ADD_DEFINITIONS(-DEIGEN_DEBUG_ASSERTS=1)
ENDIF(EIGEN_DEBUG_ASSERTS)
ELSE(NOT EIGEN_NO_ASSERTION_CHECKING)
ADD_DEFINITIONS(-DEIGEN_NO_ASSERTION_CHECKING=1)
ENDIF(NOT EIGEN_NO_ASSERTION_CHECKING)
ADD_TEST(Eigen test)
EI_ADD_TEST(basicstuff)
EI_ADD_TEST(miscmatrices)
EI_ADD_TEST(adjoint)
EI_ADD_TEST(submatrices)
EI_ADD_TEST(smallvectors)
EI_ADD_TEST(cwiseop)
EI_ADD_TEST(map)
EI_ADD_TEST(linearstructure)
EI_ADD_TEST(product)
EI_ADD_TEST(triangular)
EI_ADD_TEST(cholesky)
# EI_ADD_TEST(determinant)
ENDIF(BUILD_TESTS)

View File

@ -24,8 +24,6 @@
#include "main.h"
namespace Eigen {
template<typename MatrixType> void adjoint(const MatrixType& m)
{
/* this test covers the following files:
@ -95,17 +93,16 @@ template<typename MatrixType> void adjoint(const MatrixType& m)
}
void EigenTest::testAdjoint()
void test_adjoint()
{
for(int i = 0; i < m_repeat; i++) {
adjoint(Matrix<float, 1, 1>());
adjoint(Matrix4d());
adjoint(MatrixXcf(3, 3));
adjoint(MatrixXi(8, 12));
adjoint(MatrixXcd(20, 20));
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( adjoint(Matrix<float, 1, 1>()) );
CALL_SUBTEST( adjoint(Matrix4d()) );
CALL_SUBTEST( adjoint(MatrixXcf(3, 3)) );
CALL_SUBTEST( adjoint(MatrixXi(8, 12)) );
CALL_SUBTEST( adjoint(MatrixXcd(20, 20)) );
}
// test a large matrix only once
adjoint(Matrix<float, 100, 100>());
CALL_SUBTEST( adjoint(Matrix<float, 100, 100>()) );
}
} // namespace Eigen

View File

@ -24,8 +24,6 @@
#include "main.h"
namespace Eigen {
template<typename MatrixType> void basicStuff(const MatrixType& m)
{
typedef typename MatrixType::Scalar Scalar;
@ -86,49 +84,14 @@ template<typename MatrixType> void basicStuff(const MatrixType& m)
}
}
void EigenTest::testBasicStuff()
void test_basicstuff()
{
for(int i = 0; i < m_repeat; i++) {
basicStuff(Matrix<float, 1, 1>());
basicStuff(Matrix4d());
basicStuff(MatrixXcf(3, 3));
basicStuff(MatrixXi(8, 12));
basicStuff(MatrixXcd(20, 20));
basicStuff(Matrix<float, 100, 100>());
}
// some additional basic tests
{
Matrix3d m3;
Matrix4d m4;
VERIFY_RAISES_ASSERT(m4 = m3);
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
double data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
m3 = Matrix3d::random();
m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
Vector3d vec[3];
vec[0] << 1, 4, 7;
vec[1] << 2, 5, 8;
vec[2] << 3, 6, 9;
m3 = Matrix3d::random();
m3 << vec[0], vec[1], vec[2];
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
vec[0] << 1, 2, 3;
vec[1] << 4, 5, 6;
vec[2] << 7, 8, 9;
m3 = Matrix3d::random();
m3 << vec[0].transpose(),
4, 5, 6,
vec[2].transpose();
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( basicStuff(Matrix<float, 1, 1>()) );
CALL_SUBTEST( basicStuff(Matrix4d()) );
CALL_SUBTEST( basicStuff(MatrixXcf(3, 3)) );
CALL_SUBTEST( basicStuff(MatrixXi(8, 12)) );
CALL_SUBTEST( basicStuff(MatrixXcd(20, 20)) );
CALL_SUBTEST( basicStuff(Matrix<float, 100, 100>()) );
}
}
} // namespace Eigen

View File

@ -23,11 +23,8 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <Eigen/Cholesky>
namespace Eigen {
template<typename MatrixType> void cholesky(const MatrixType& m)
{
/* this test covers the following files:
@ -53,13 +50,11 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
VERIFY_IS_APPROX(covMat * chol.solve(b), b);
}
void EigenTest::testCholesky()
void test_cholesky()
{
for(int i = 0; i < 1; i++) {
cholesky(Matrix3f());
cholesky(Matrix4d());
cholesky(MatrixXcd(7,7));
CALL_SUBTEST( cholesky(Matrix3f()) );
CALL_SUBTEST( cholesky(Matrix4d()) );
CALL_SUBTEST( cholesky(MatrixXcd(7,7)) );
}
}
} // namespace Eigen

58
test/commainitializer.cpp Normal file
View File

@ -0,0 +1,58 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
void test_commainitializer()
{
Matrix3d m3;
Matrix4d m4;
VERIFY_RAISES_ASSERT(m4 = m3);
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
double data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
m3 = Matrix3d::random();
m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
Vector3d vec[3];
vec[0] << 1, 4, 7;
vec[1] << 2, 5, 8;
vec[2] << 3, 6, 9;
m3 = Matrix3d::random();
m3 << vec[0], vec[1], vec[2];
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
vec[0] << 1, 2, 3;
vec[1] << 4, 5, 6;
vec[2] << 7, 8, 9;
m3 = Matrix3d::random();
m3 << vec[0].transpose(),
4, 5, 6,
vec[2].transpose();
VERIFY_IS_APPROX(m3, (Matrix<double,3,3,RowMajorBit>::map(data)) );
}

View File

@ -24,15 +24,10 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <functional>
using namespace std;
namespace Eigen {
template<typename Scalar> struct AddIfNull {
const Scalar operator() (const Scalar a, const Scalar b) const {return a<=1e-3 ? b : a;}
enum { Cost = NumTraits<Scalar>::AddCost };
@ -76,15 +71,13 @@ template<typename MatrixType> void cwiseops(const MatrixType& m)
// VERIFY_IS_APPROX( cwiseMin(m1,m1-mones), m1-mones );
}
void EigenTest::testCwiseops()
void test_cwiseop()
{
for(int i = 0; i < m_repeat ; i++) {
cwiseops(Matrix<float, 1, 1>());
cwiseops(Matrix4d());
cwiseops(MatrixXf(3, 3));
cwiseops(MatrixXi(8, 12));
cwiseops(MatrixXd(20, 20));
for(int i = 0; i < g_repeat ; i++) {
CALL_SUBTEST( cwiseops(Matrix<float, 1, 1>()) );
CALL_SUBTEST( cwiseops(Matrix4d()) );
CALL_SUBTEST( cwiseops(MatrixXf(3, 3)) );
CALL_SUBTEST( cwiseops(MatrixXi(8, 12)) );
CALL_SUBTEST( cwiseops(MatrixXd(20, 20)) );
}
}
} // namespace Eigen

View File

@ -23,11 +23,8 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
#include <Eigen/LU>
namespace Eigen {
template<typename MatrixType> void nullDeterminant(const MatrixType& m)
{
/* this test covers the following files:
@ -69,15 +66,13 @@ template<typename MatrixType> void nullDeterminant(const MatrixType& m)
VERIFY(!notInvertibleCovarianceMatrix.inverse().exists());
}
void EigenTest::testDeterminant()
void test_determinant()
{
for(int i = 0; i < m_repeat; i++) {
nullDeterminant(Matrix<float, 30, 3>());
nullDeterminant(Matrix<double, 30, 3>());
nullDeterminant(Matrix<float, 20, 4>());
nullDeterminant(Matrix<double, 20, 4>());
// nullDeterminant(MatrixXd(20,4));
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( nullDeterminant(Matrix<float, 30, 3>()) );
CALL_SUBTEST( nullDeterminant(Matrix<double, 30, 3>()) );
CALL_SUBTEST( nullDeterminant(Matrix<float, 20, 4>()) );
CALL_SUBTEST( nullDeterminant(Matrix<double, 20, 4>()) );
// CALL_SUBTEST( nullDeterminant(MatrixXd(20,4));
}
}
} // namespace Eigen

View File

@ -24,8 +24,6 @@
#include "main.h"
namespace Eigen {
template<typename MatrixType> void linearStructure(const MatrixType& m)
{
/* this test covers the following files:
@ -97,16 +95,14 @@ template<typename MatrixType> void linearStructure(const MatrixType& m)
VERIFY_IS_APPROX(m1.block(0,0,rows,cols) * s1, m1 * s1);
}
void EigenTest::testLinearStructure()
void test_linearstructure()
{
for(int i = 0; i < m_repeat; i++) {
linearStructure(Matrix<float, 1, 1>());
linearStructure(Matrix4d());
linearStructure(MatrixXcf(3, 3));
linearStructure(MatrixXf(8, 12));
linearStructure(MatrixXi(8, 12));
linearStructure(MatrixXcd(20, 20));
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( linearStructure(Matrix<float, 1, 1>()) );
CALL_SUBTEST( linearStructure(Matrix4d()) );
CALL_SUBTEST( linearStructure(MatrixXcf(3, 3)) );
CALL_SUBTEST( linearStructure(MatrixXf(8, 12)) );
CALL_SUBTEST( linearStructure(MatrixXi(8, 12)) );
CALL_SUBTEST( linearStructure(MatrixXcd(20, 20)) );
}
}
} // namespace Eigen

View File

@ -1,97 +0,0 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
bool has_set_repeat = false;
bool has_set_seed = false;
bool need_help = false;
unsigned int seed;
int repeat;
QStringList args = QCoreApplication::instance()->arguments();
args.takeFirst(); // throw away the first argument (path to executable)
foreach(QString arg, args)
{
if(arg.startsWith("r"))
{
if(has_set_repeat)
{
qDebug() << "Argument" << arg << "conflicting with a former argument";
return 1;
}
repeat = arg.remove(0, 1).toInt();
has_set_repeat = true;
if(repeat <= 0)
{
qDebug() << "Invalid \'repeat\' value" << arg;
return 1;
}
}
else if(arg.startsWith("s"))
{
if(has_set_seed)
{
qDebug() << "Argument" << arg << "conflicting with a former argument";
return 1;
}
bool ok;
seed = arg.remove(0, 1).toUInt(&ok);
has_set_seed = true;
if(!ok)
{
qDebug() << "Invalid \'seed\' value" << arg;
return 1;
}
}
else
{
need_help = true;
}
}
if(need_help)
{
qDebug() << "This test application takes the following optional arguments:";
qDebug() << " rN Repeat each test N times (default:" << DEFAULT_REPEAT << ")";
qDebug() << " sN Use N as seed for random numbers (default: based on current time)";
return 1;
}
if(!has_set_seed) seed = (unsigned int) time(NULL);
if(!has_set_repeat) repeat = DEFAULT_REPEAT;
qDebug() << "Initializing random number generator with seed" << seed;
srand(seed);
qDebug() << "Repeating each test" << repeat << "times";
Eigen::EigenTest test(repeat);
return QTest::qExec(&test, 1, argv);
}
#include "main.moc"

View File

@ -23,17 +23,31 @@
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#ifndef EIGEN_TEST_MAIN_H
#define EIGEN_TEST_MAIN_H
#include <QtTest/QtTest>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <Qt/QtCore>
#ifndef EIGEN_TEST_FUNC
#error EIGEN_TEST_FUNC must be defined
#endif
#define DEFAULT_REPEAT 10
namespace Eigen
{
static std::vector<std::string> g_test_stack;
static int g_repeat;
}
#define EI_PP_MAKE_STRING2(S) #S
#define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)
#define EI_PP_CAT2(a,b) a ## b
#define EI_PP_CAT(a,b) EI_PP_CAT2(a,b)
#ifndef EIGEN_NO_ASSERTION_CHECKING
namespace Eigen
@ -52,9 +66,6 @@
};
}
#define EI_PP_MAKE_STRING2(S) #S
#define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)
// If EIGEN_DEBUG_ASSERTS is defined and if no assertion is raised while
// one should have been, then the list of excecuted assertions is printed out.
//
@ -88,12 +99,12 @@
Eigen::ei_push_assert = true; \
a; \
Eigen::ei_push_assert = false; \
std::cout << "One of the following asserts should have been raised:\n"; \
std::cerr << "One of the following asserts should have been raised:\n"; \
for (uint ai=0 ; ai<ei_assert_list.size() ; ++ai) \
std::cout << " " << ei_assert_list[ai] << "\n"; \
QVERIFY(Eigen::should_raise_an_assert && # a); \
std::cerr << " " << ei_assert_list[ai] << "\n"; \
VERIFY(Eigen::should_raise_an_assert && # a); \
} catch (Eigen::ei_assert_exception e) { \
Eigen::ei_push_assert = false; QVERIFY(true); \
Eigen::ei_push_assert = false; VERIFY(true); \
} \
}
@ -108,8 +119,8 @@
#define VERIFY_RAISES_ASSERT(a) \
{ \
try { a; QVERIFY(Eigen::should_raise_an_assert && # a); } \
catch (Eigen::ei_assert_exception e) { QVERIFY(true); } \
try { a; VERIFY(Eigen::should_raise_an_assert && # a); } \
catch (Eigen::ei_assert_exception e) { VERIFY(true); } \
}
#endif // EIGEN_DEBUG_ASSERTS
@ -127,13 +138,24 @@
#define EIGEN_INTERNAL_DEBUGGING
#include <Eigen/Core>
#define VERIFY(a) QVERIFY(a)
#define VERIFY_IS_APPROX(a, b) QVERIFY(test_ei_isApprox(a, b))
#define VERIFY_IS_NOT_APPROX(a, b) QVERIFY(!test_ei_isApprox(a, b))
#define VERIFY_IS_MUCH_SMALLER_THAN(a, b) QVERIFY(test_ei_isMuchSmallerThan(a, b))
#define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) QVERIFY(!test_ei_isMuchSmallerThan(a, b))
#define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) QVERIFY(test_ei_isApproxOrLessThan(a, b))
#define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) QVERIFY(!test_ei_isApproxOrLessThan(a, b))
#define VERIFY(a) do { if (!(a)) { \
std::cerr << "Test " << g_test_stack.back() << " failed in "EI_PP_MAKE_STRING(__FILE__) << " (" << EI_PP_MAKE_STRING(__LINE__) << ")" \
<< std::endl << " " << EI_PP_MAKE_STRING(a) << std::endl << std::endl; \
exit(2); \
} } while (0)
#define VERIFY_IS_APPROX(a, b) VERIFY(test_ei_isApprox(a, b))
#define VERIFY_IS_NOT_APPROX(a, b) VERIFY(!test_ei_isApprox(a, b))
#define VERIFY_IS_MUCH_SMALLER_THAN(a, b) VERIFY(test_ei_isMuchSmallerThan(a, b))
#define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) VERIFY(!test_ei_isMuchSmallerThan(a, b))
#define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) VERIFY(test_ei_isApproxOrLessThan(a, b))
#define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) VERIFY(!test_ei_isApproxOrLessThan(a, b))
#define CALL_SUBTEST(FUNC) do { \
g_test_stack.push_back(EI_PP_MAKE_STRING(FUNC)); \
FUNC; \
g_test_stack.pop_back(); \
} while (0)
namespace Eigen {
@ -196,30 +218,86 @@ inline bool test_ei_isMuchSmallerThan(const MatrixBase<Derived>& m,
return m.isMuchSmallerThan(s, test_precision<typename ei_traits<Derived>::Scalar>());
}
class EigenTest : public QObject
{
Q_OBJECT
public:
EigenTest(int repeat) : m_repeat(repeat) {}
private slots:
void testBasicStuff();
void testLinearStructure();
void testProduct();
void testAdjoint();
void testSubmatrices();
void testMiscMatrices();
void testSmallVectors();
void testMap();
void testCwiseops();
//void testDeterminant(); //determinant for size > 4x4 unimplemented for now
void testTriangular();
void testCholesky();
protected:
int m_repeat;
};
} // end namespace Eigen
#endif // EIGEN_TEST_MAIN_H
// forward declaration of the main test function
void EI_PP_CAT(test_,EIGEN_TEST_FUNC)();
using namespace Eigen;
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
bool has_set_repeat = false;
bool has_set_seed = false;
bool need_help = false;
unsigned int seed = 0;
int repeat = DEFAULT_REPEAT;
QStringList args = QCoreApplication::instance()->arguments();
args.takeFirst(); // throw away the first argument (path to executable)
foreach(QString arg, args)
{
if(arg.startsWith("r"))
{
if(has_set_repeat)
{
qDebug() << "Argument" << arg << "conflicting with a former argument";
return 1;
}
repeat = arg.remove(0, 1).toInt();
has_set_repeat = true;
if(repeat <= 0)
{
qDebug() << "Invalid \'repeat\' value" << arg;
return 1;
}
}
else if(arg.startsWith("s"))
{
if(has_set_seed)
{
qDebug() << "Argument" << arg << "conflicting with a former argument";
return 1;
}
bool ok;
seed = arg.remove(0, 1).toUInt(&ok);
has_set_seed = true;
if(!ok)
{
qDebug() << "Invalid \'seed\' value" << arg;
return 1;
}
}
else
{
need_help = true;
}
}
if(need_help)
{
qDebug() << "This test application takes the following optional arguments:";
qDebug() << " rN Repeat each test N times (default:" << DEFAULT_REPEAT << ")";
qDebug() << " sN Use N as seed for random numbers (default: based on current time)";
return 1;
}
if(!has_set_seed) seed = (unsigned int) time(NULL);
if(!has_set_repeat) repeat = DEFAULT_REPEAT;
qDebug() << "Initializing random number generator with seed" << seed;
srand(seed);
qDebug() << "Repeating each test" << repeat << "times";
Eigen::g_repeat = repeat;
Eigen::g_test_stack.push_back(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC));
EI_PP_CAT(test_,EIGEN_TEST_FUNC)();
return 0;
}

View File

@ -5,12 +5,12 @@
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
@ -18,20 +18,18 @@
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
namespace Eigen {
template<typename VectorType> void tmap(const VectorType& m)
{
typedef typename VectorType::Scalar Scalar;
int size = m.size();
// test Map.h
Scalar* array1 = new Scalar[size];
Scalar* array2 = new Scalar[size];
@ -45,15 +43,13 @@ template<typename VectorType> void tmap(const VectorType& m)
delete[] array2;
}
void EigenTest::testMap()
void test_map()
{
for(int i = 0; i < m_repeat; i++) {
tmap(Matrix<float, 1, 1>());
tmap(Vector4d());
tmap(RowVector4f());
tmap(VectorXcf(8));
tmap(VectorXi(12));
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( tmap(Matrix<float, 1, 1>()) );
CALL_SUBTEST( tmap(Vector4d()) );
CALL_SUBTEST( tmap(RowVector4f()) );
CALL_SUBTEST( tmap(VectorXcf(8)) );
CALL_SUBTEST( tmap(VectorXi(12)) );
}
}
} // namespace Eigen

View File

@ -5,12 +5,12 @@
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
@ -18,14 +18,12 @@
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
namespace Eigen {
template<typename MatrixType> void miscMatrices(const MatrixType& m)
{
/* this test covers the following files:
@ -37,7 +35,7 @@ template<typename MatrixType> void miscMatrices(const MatrixType& m)
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
int rows = m.rows();
int cols = m.cols();
int r = ei_random<int>(0, rows-1), r2 = ei_random<int>(0, rows-1), c = ei_random<int>(0, cols-1);
VERIFY_IS_APPROX(MatrixType::ones(rows,cols)(r,c), static_cast<Scalar>(1));
MatrixType m1 = MatrixType::ones(rows,cols);
@ -53,15 +51,13 @@ template<typename MatrixType> void miscMatrices(const MatrixType& m)
VERIFY_IS_APPROX(square, MatrixType::identity(rows, rows));
}
void EigenTest::testMiscMatrices()
void test_miscmatrices()
{
for(int i = 0; i < m_repeat; i++) {
miscMatrices(Matrix<float, 1, 1>());
miscMatrices(Matrix4d());
miscMatrices(MatrixXcf(3, 3));
miscMatrices(MatrixXi(8, 12));
miscMatrices(MatrixXcd(20, 20));
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( miscMatrices(Matrix<float, 1, 1>()) );
CALL_SUBTEST( miscMatrices(Matrix4d()) );
CALL_SUBTEST( miscMatrices(MatrixXcf(3, 3)) );
CALL_SUBTEST( miscMatrices(MatrixXi(8, 12)) );
CALL_SUBTEST( miscMatrices(MatrixXcd(20, 20)) );
}
}
} // namespace Eigen

View File

@ -24,8 +24,6 @@
#include "main.h"
namespace Eigen {
template<typename MatrixType> void product(const MatrixType& m)
{
/* this test covers the following files:
@ -91,23 +89,23 @@ template<typename MatrixType> void product(const MatrixType& m)
VERIFY_RAISES_ASSERT(m3 = m1*m1);
}
void EigenTest::testProduct()
void test_product()
{
for(int i = 0; i < m_repeat; i++) {
product(Matrix<float, 1, 1>());
product(Matrix<float, 3, 3>());
product(Matrix<float, 4, 2>());
product(Matrix4d());
}
for(int i = 0; i < m_repeat; i++) {
// for(int i = 0; i < g_repeat; i++) {
// CALL_SUBTEST( product(Matrix<float, 1, 1>()) );
// CALL_SUBTEST( product(Matrix<float, 3, 3>()) );
// CALL_SUBTEST( product(Matrix<float, 4, 2>()) );
// CALL_SUBTEST( product(Matrix4d()) );
// }
for(int i = 0; i < g_repeat; i++) {
int rows = ei_random<int>(1,320);
int cols = ei_random<int>(1,320);
product(MatrixXf(rows, cols));
product(MatrixXd(rows, cols));
product(MatrixXi(rows, cols));
product(MatrixXcf(rows, cols));
product(MatrixXcd(rows, cols));
std::cout << "test MatrixXf " << rows << "x" << cols << "\n";
CALL_SUBTEST( product(MatrixXf(rows, cols)) );
std::cout << "test MatrixXd " << rows << "x" << cols << "\n";
CALL_SUBTEST( product(MatrixXd(rows, cols)) );
// CALL_SUBTEST( product(MatrixXi(rows, cols)) );
// CALL_SUBTEST( product(MatrixXcf(rows, cols)) );
// CALL_SUBTEST( product(MatrixXcd(rows, cols)) );
}
}
} // namespace Eigen

28
test/runtest.sh Executable file
View File

@ -0,0 +1,28 @@
#!/bin/bash
black='\E[30m'
red='\E[31m'
green='\E[32m'
yellow='\E[33m'
blue='\E[34m'
magenta='\E[35m'
cyan='\E[36m'
white='\E[37m'
if make test_$1 > /dev/null 2> .runtest.log ; then
if ! ./test_$1 > /dev/null 2> .runtest.log ; then
echo -e $red Test $1 failed: $black
echo -e $blue
cat .runtest.log
echo -e $black
exit 1
else
echo -e $green Test $1 passed$black
fi
else
echo -e $red Build of target $1 failed: $black
echo -e $blue
cat .runtest.log
echo -e $black
exit 1
fi

View File

@ -5,12 +5,12 @@
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
@ -18,14 +18,12 @@
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
namespace Eigen {
template<typename Scalar> void smallVectors()
{
typedef Matrix<Scalar, 1, 2> V2;
@ -49,13 +47,11 @@ template<typename Scalar> void smallVectors()
VERIFY_IS_APPROX(x4, v4.w());
}
void EigenTest::testSmallVectors()
void test_smallvectors()
{
for(int i = 0; i < m_repeat; i++) {
smallVectors<int>();
smallVectors<float>();
smallVectors<double>();
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( smallVectors<int>() );
CALL_SUBTEST( smallVectors<float>() );
CALL_SUBTEST( smallVectors<double>() );
}
}
} // namespace Eigen

View File

@ -24,8 +24,6 @@
#include "main.h"
namespace Eigen {
// check minor separately in order to avoid the possible creation of a zero-sized
// array. Comes from a compilation error with gcc-3.4 or gcc-4 with -ansi -pedantic.
// Another solution would be to declare the array like this: T m_data[Size==0?1:Size]; in ei_matrix_storage
@ -63,7 +61,7 @@ template<typename MatrixType> void submatrices(const MatrixType& m)
typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
int rows = m.rows();
int cols = m.cols();
MatrixType m1 = MatrixType::random(rows, cols),
m2 = MatrixType::random(rows, cols),
m3(rows, cols),
@ -101,39 +99,37 @@ template<typename MatrixType> void submatrices(const MatrixType& m)
//check operator(), both constant and non-constant, on block()
m1.block(r1,c1,r2-r1+1,c2-c1+1) = s1 * m2.block(0, 0, r2-r1+1,c2-c1+1);
m1.block(r1,c1,r2-r1+1,c2-c1+1)(r2-r1,c2-c1) = m2.block(0, 0, r2-r1+1,c2-c1+1)(0,0);
//check minor()
CheckMinor<Scalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> checkminor(m1,r1,c1);
//check diagonal()
VERIFY_IS_APPROX(m1.diagonal(), m1.transpose().diagonal());
m2.diagonal() = 2 * m1.diagonal();
m2.diagonal()[0] *= 3;
VERIFY_IS_APPROX(m2.diagonal()[0], static_cast<Scalar>(6) * m1.diagonal()[0]);
}
void EigenTest::testSubmatrices()
{
for(int i = 0; i < m_repeat; i++) {
submatrices(Matrix<float, 1, 1>());
submatrices(Matrix4d());
submatrices(MatrixXcf(3, 3));
submatrices(MatrixXi(8, 12));
submatrices(MatrixXcd(20, 20));
// test fixed block() separately as it is a template method so doesn't support
// being called as a member of a class that is itself a template parameter
// (at least as of g++ 4.2)
Matrix<float, 6, 8> m = Matrix<float, 6, 8>::random();
float s = ei_random<float>();
const int BlockRows = EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime,2);
const int BlockCols = EIGEN_ENUM_MIN(MatrixType::ColsAtCompileTime,5);
if (rows>=5 && cols>=8)
{
// test fixed block() as lvalue
m.block<2,5>(1,1) *= s;
m1.template block<BlockRows,BlockCols>(1,1) *= s1;
// test operator() on fixed block() both as constant and non-constant
m.block<2,5>(1,1)(0, 3) = m.block<2,5>(1,1)(1,2);
m1.template block<BlockRows,BlockCols>(1,1)(0, 3) = m1.template block<2,5>(1,1)(1,2);
// check that fixed block() and block() agree
MatrixXf b = m.block<3,2>(3,3);
VERIFY_IS_APPROX(b, m.block(3,3,3,2));
Matrix<Scalar,Dynamic,Dynamic> b = m1.template block<BlockRows,BlockCols>(3,3);
VERIFY_IS_APPROX(b, m1.block(3,3,BlockRows,BlockCols));
}
}
} // namespace Eigen
void test_submatrices()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( submatrices(Matrix<float, 1, 1>()) );
CALL_SUBTEST( submatrices(Matrix4d()) );
CALL_SUBTEST( submatrices(MatrixXcf(3, 3)) );
CALL_SUBTEST( submatrices(MatrixXi(8, 12)) );
CALL_SUBTEST( submatrices(MatrixXcd(20, 20)) );
}
}

View File

@ -24,8 +24,6 @@
#include "main.h"
namespace Eigen {
template<typename MatrixType> void triangular(const MatrixType& m)
{
typedef typename MatrixType::Scalar Scalar;
@ -87,14 +85,12 @@ template<typename MatrixType> void triangular(const MatrixType& m)
}
void EigenTest::testTriangular()
void test_triangular()
{
for(int i = 0; i < m_repeat ; i++) {
for(int i = 0; i < g_repeat ; i++) {
// triangular(Matrix<float, 1, 1>());
triangular(Matrix3d());
triangular(MatrixXcf(4, 4));
// triangular(Matrix<std::complex<float>,8, 8>());
CALL_SUBTEST( triangular(Matrix3d()) );
CALL_SUBTEST( triangular(MatrixXcf(4, 4)) );
// CALL_SUBTEST( triangular(Matrix<std::complex<float>,8, 8>()) );
}
}
} // namespace Eigen