mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
merge with default branch
This commit is contained in:
@@ -3,10 +3,6 @@ add_custom_target(buildtests)
|
||||
add_custom_target(check COMMAND "ctest")
|
||||
add_dependencies(check buildtests)
|
||||
|
||||
|
||||
include(EigenTesting)
|
||||
ei_init_testing()
|
||||
|
||||
option(EIGEN_SPLIT_LARGE_TESTS "Split large tests into smaller executables" ON)
|
||||
|
||||
find_package(GSL)
|
||||
@@ -162,6 +158,8 @@ ei_add_test(conservative_resize)
|
||||
ei_add_test(permutationmatrices)
|
||||
ei_add_test(eigen2support)
|
||||
|
||||
ei_add_test(prec_inverse_4x4)
|
||||
|
||||
ei_add_property(EIGEN_TESTING_SUMMARY "CXX: ${CMAKE_CXX_COMPILER}\n")
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version COMMAND head -n 1 OUTPUT_VARIABLE EIGEN_CXX_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
@@ -169,5 +167,3 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
ei_add_property(EIGEN_TESTING_SUMMARY "CXX_FLAGS: ${CMAKE_CXX_FLAGS}\n")
|
||||
ei_add_property(EIGEN_TESTING_SUMMARY "Sparse lib flags: ${SPARSE_LIBS}\n")
|
||||
|
||||
configure_file(buildtests.in ${CMAKE_BINARY_DIR}/buildtests)
|
||||
|
||||
@@ -128,6 +128,14 @@ void test_adjoint()
|
||||
VERIFY_RAISES_ASSERT(a = a.adjoint());
|
||||
VERIFY_RAISES_ASSERT(a = a.adjoint() + b);
|
||||
VERIFY_RAISES_ASSERT(a = b + a.adjoint());
|
||||
|
||||
// no assertion should be triggered for these cases:
|
||||
a.transpose() = a.transpose();
|
||||
a.transpose() += a.transpose();
|
||||
a.transpose() += a.transpose() + b;
|
||||
a.transpose() = a.adjoint();
|
||||
a.transpose() += a.adjoint();
|
||||
a.transpose() += a.adjoint() + b;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ template<typename MatrixType> void bandmatrix(const MatrixType& _m)
|
||||
dm1.diagonal(-i).setConstant(-static_cast<RealScalar>(i));
|
||||
}
|
||||
//std::cerr << m.m_data << "\n\n" << m.toDense() << "\n\n" << dm1 << "\n\n\n\n";
|
||||
VERIFY_IS_APPROX(dm1,m.toDense());
|
||||
VERIFY_IS_APPROX(dm1,m.toDenseMatrix());
|
||||
|
||||
for (int i=0; i<cols; ++i)
|
||||
{
|
||||
@@ -68,7 +68,7 @@ template<typename MatrixType> void bandmatrix(const MatrixType& _m)
|
||||
dm1.block(subs+1,0,rows-subs-1-b,rows-subs-1-b).template triangularView<LowerTriangular>().setZero();
|
||||
if(b>0) dm1.block(d+subs,0,b,cols).setZero();
|
||||
//std::cerr << m.m_data << "\n\n" << m.toDense() << "\n\n" << dm1 << "\n\n";
|
||||
VERIFY_IS_APPROX(dm1,m.toDense());
|
||||
VERIFY_IS_APPROX(dm1,m.toDenseMatrix());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ $# == 0 -o $# -ge 3 ]
|
||||
then
|
||||
echo "usage: ./buildtests regexp [jobs]"
|
||||
echo " makes tests matching the regexp, with <jobs> concurrent make jobs"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TESTSLIST="${cmake_tests_list}"
|
||||
targets_to_make=`echo "$TESTSLIST" | grep "$1" | sed s/^/test_/g | xargs echo`
|
||||
|
||||
if [ $# == 1 ]
|
||||
then
|
||||
make $targets_to_make
|
||||
fi
|
||||
|
||||
if [ $# == 2 ]
|
||||
then
|
||||
make -j $2 $targets_to_make
|
||||
fi
|
||||
@@ -95,7 +95,7 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
|
||||
|
||||
{
|
||||
LLT<SquareMatrixType,LowerTriangular> chollo(symmLo);
|
||||
VERIFY_IS_APPROX(symm, chollo.matrixL().toDense() * chollo.matrixL().adjoint().toDense());
|
||||
VERIFY_IS_APPROX(symm, chollo.matrixL().toDenseMatrix() * chollo.matrixL().adjoint().toDenseMatrix());
|
||||
vecX = chollo.solve(vecB);
|
||||
VERIFY_IS_APPROX(symm * vecX, vecB);
|
||||
matX = chollo.solve(matB);
|
||||
@@ -103,7 +103,7 @@ template<typename MatrixType> void cholesky(const MatrixType& m)
|
||||
|
||||
// test the upper mode
|
||||
LLT<SquareMatrixType,UpperTriangular> cholup(symmUp);
|
||||
VERIFY_IS_APPROX(symm, cholup.matrixL().toDense() * cholup.matrixL().adjoint().toDense());
|
||||
VERIFY_IS_APPROX(symm, cholup.matrixL().toDenseMatrix() * cholup.matrixL().adjoint().toDenseMatrix());
|
||||
vecX = cholup.solve(vecB);
|
||||
VERIFY_IS_APPROX(symm * vecX, vecB);
|
||||
matX = cholup.solve(matB);
|
||||
|
||||
@@ -60,5 +60,6 @@ void test_eigensolver_complex()
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( eigensolver(Matrix4cf()) );
|
||||
CALL_SUBTEST_2( eigensolver(MatrixXcd(14,14)) );
|
||||
CALL_SUBTEST_3( eigensolver(Matrix<std::complex<float>, 1, 1>()) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
|
||||
// transform
|
||||
if (!NumTraits<Scalar>::IsComplex)
|
||||
{
|
||||
MatrixType rot = MatrixType::Random(dim,dim).householderQr().matrixQ();
|
||||
MatrixType rot = MatrixType::Random(dim,dim).householderQr().householderQ();
|
||||
DiagonalMatrix<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random());
|
||||
Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random());
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ template<typename Scalar> void quaternion(void)
|
||||
if (ei_is_same_type<Scalar,float>::ret)
|
||||
largeEps = 1e-3f;
|
||||
|
||||
Scalar eps = ei_random<Scalar>() * 1e-2;
|
||||
Scalar eps = ei_random<Scalar>() * Scalar(1e-2);
|
||||
|
||||
Vector3 v0 = Vector3::Random(),
|
||||
v1 = Vector3::Random(),
|
||||
|
||||
@@ -38,18 +38,11 @@ template<typename MatrixType> void inverse(const MatrixType& m)
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
MatrixType m1(rows, cols),
|
||||
m2(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
identity = MatrixType::Identity(rows, rows);
|
||||
|
||||
if (ei_is_same_type<RealScalar,float>::ret)
|
||||
{
|
||||
// let's build a more stable to inverse matrix
|
||||
MatrixType a = MatrixType::Random(rows,cols);
|
||||
m1 += m1 * m1.adjoint() + a * a.adjoint();
|
||||
}
|
||||
|
||||
createRandomMatrixOfRank(rows,rows,rows,m1);
|
||||
m2 = m1.inverse();
|
||||
VERIFY_IS_APPROX(m1, m2.inverse() );
|
||||
|
||||
@@ -104,12 +97,4 @@ void test_inverse()
|
||||
s = ei_random<int>(25,100);
|
||||
CALL_SUBTEST_6( inverse(MatrixXcd(s,s)) );
|
||||
}
|
||||
|
||||
#ifdef EIGEN_TEST_PART_4
|
||||
// test some tricky cases for 4x4 matrices
|
||||
VERIFY_IS_APPROX((Matrix4f() << 0,0,1,0, 1,0,0,0, 0,1,0,0, 0,0,0,1).finished().inverse(),
|
||||
(Matrix4f() << 0,1,0,0, 0,0,1,0, 1,0,0,0, 0,0,0,1).finished());
|
||||
VERIFY_IS_APPROX((Matrix4f() << 1,0,0,0, 0,0,1,0, 0,0,0,1, 0,1,0,0).finished().inverse(),
|
||||
(Matrix4f() << 1,0,0,0, 0,0,0,1, 0,1,0,0, 0,0,1,0).finished());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -54,6 +54,9 @@ template<typename MatrixType, unsigned int Options> void svd(const MatrixType& m
|
||||
MatrixUType u = svd.matrixU();
|
||||
MatrixVType v = svd.matrixV();
|
||||
|
||||
std::cout << "a\n" << a << std::endl;
|
||||
std::cout << "b\n" << u * sigma * v.adjoint() << std::endl;
|
||||
|
||||
VERIFY_IS_APPROX(a, u * sigma * v.adjoint());
|
||||
VERIFY_IS_UNITARY(u);
|
||||
VERIFY_IS_UNITARY(v);
|
||||
|
||||
17
test/lu.cpp
17
test/lu.cpp
@@ -24,9 +24,11 @@
|
||||
|
||||
#include "main.h"
|
||||
#include <Eigen/LU>
|
||||
using namespace std;
|
||||
|
||||
template<typename MatrixType> void lu_non_invertible()
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
/* this test covers the following files:
|
||||
LU.h
|
||||
*/
|
||||
@@ -65,7 +67,20 @@ template<typename MatrixType> void lu_non_invertible()
|
||||
createRandomMatrixOfRank(rank, rows, cols, m1);
|
||||
|
||||
FullPivLU<MatrixType> lu(m1);
|
||||
std::cout << lu.kernel().rows() << " " << lu.kernel().cols() << std::endl;
|
||||
// FIXME need better way to construct trapezoid matrices. extend triangularView to support rectangular.
|
||||
DynamicMatrixType u(rows,cols);
|
||||
for(int i = 0; i < rows; i++)
|
||||
for(int j = 0; j < cols; j++)
|
||||
u(i,j) = i>j ? Scalar(0) : lu.matrixLU()(i,j);
|
||||
DynamicMatrixType l(rows,rows);
|
||||
for(int i = 0; i < rows; i++)
|
||||
for(int j = 0; j < rows; j++)
|
||||
l(i,j) = (i<j || j>=cols) ? Scalar(0)
|
||||
: i==j ? Scalar(1)
|
||||
: lu.matrixLU()(i,j);
|
||||
|
||||
VERIFY_IS_APPROX(lu.permutationP() * m1 * lu.permutationQ(), l*u);
|
||||
|
||||
KernelMatrixType m1kernel = lu.kernel();
|
||||
ImageMatrixType m1image = lu.image(m1);
|
||||
|
||||
|
||||
102
test/main.h
102
test/main.h
@@ -24,6 +24,7 @@
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cerrno>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
@@ -49,6 +50,8 @@ namespace Eigen
|
||||
{
|
||||
static std::vector<std::string> g_test_stack;
|
||||
static int g_repeat;
|
||||
static unsigned int g_seed;
|
||||
static bool g_has_set_repeat, g_has_set_seed;
|
||||
}
|
||||
|
||||
#define EI_PP_MAKE_STRING2(S) #S
|
||||
@@ -350,17 +353,30 @@ void createRandomMatrixOfRank(int desired_rank, int rows, int cols, MatrixType&
|
||||
typedef Matrix<Scalar, Rows, Rows> MatrixAType;
|
||||
typedef Matrix<Scalar, Cols, Cols> MatrixBType;
|
||||
|
||||
if(desired_rank == 0)
|
||||
{
|
||||
m.setZero(rows,cols);
|
||||
return;
|
||||
}
|
||||
|
||||
if(desired_rank == 1)
|
||||
{
|
||||
m = VectorType::Random(rows) * VectorType::Random(cols).transpose();
|
||||
return;
|
||||
}
|
||||
|
||||
MatrixAType a = MatrixAType::Random(rows,rows);
|
||||
MatrixType d = MatrixType::Identity(rows,cols);
|
||||
MatrixBType b = MatrixBType::Random(cols,cols);
|
||||
|
||||
// set the diagonal such that only desired_rank non-zero entries reamain
|
||||
const int diag_size = std::min(d.rows(),d.cols());
|
||||
d.diagonal().segment(desired_rank, diag_size-desired_rank) = VectorType::Zero(diag_size-desired_rank);
|
||||
if(diag_size != desired_rank)
|
||||
d.diagonal().segment(desired_rank, diag_size-desired_rank) = VectorType::Zero(diag_size-desired_rank);
|
||||
|
||||
HouseholderQR<MatrixAType> qra(a);
|
||||
HouseholderQR<MatrixBType> qrb(b);
|
||||
m = qra.matrixQ() * d * qrb.matrixQ();
|
||||
m = qra.householderQ() * d * qrb.householderQ();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
@@ -372,51 +388,68 @@ template<> struct GetDifferentType<double> { typedef float type; };
|
||||
template<typename T> struct GetDifferentType<std::complex<T> >
|
||||
{ typedef std::complex<typename GetDifferentType<T>::type> type; };
|
||||
|
||||
template<typename T> std::string type_name() { return "other"; }
|
||||
template<> std::string type_name<float>() { return "float"; }
|
||||
template<> std::string type_name<double>() { return "double"; }
|
||||
template<> std::string type_name<int>() { return "int"; }
|
||||
template<> std::string type_name<std::complex<float> >() { return "complex<float>"; }
|
||||
template<> std::string type_name<std::complex<double> >() { return "complex<double>"; }
|
||||
template<> std::string type_name<std::complex<int> >() { return "complex<int>"; }
|
||||
|
||||
// forward declaration of the main test function
|
||||
void EIGEN_CAT(test_,EIGEN_TEST_FUNC)();
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
void set_repeat_from_string(const char *str)
|
||||
{
|
||||
errno = 0;
|
||||
g_repeat = int(strtoul(str, 0, 10));
|
||||
if(errno || g_repeat <= 0)
|
||||
{
|
||||
std::cout << "Invalid repeat value " << str << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_has_set_repeat = true;
|
||||
}
|
||||
|
||||
void set_seed_from_string(const char *str)
|
||||
{
|
||||
errno = 0;
|
||||
g_seed = strtoul(str, 0, 10);
|
||||
if(errno || g_seed == 0)
|
||||
{
|
||||
std::cout << "Invalid seed value " << str << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
g_has_set_seed = true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
bool has_set_repeat = false;
|
||||
bool has_set_seed = false;
|
||||
g_has_set_repeat = false;
|
||||
g_has_set_seed = false;
|
||||
bool need_help = false;
|
||||
unsigned int seed = 0;
|
||||
int repeat = DEFAULT_REPEAT;
|
||||
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
if(argv[i][0] == 'r')
|
||||
{
|
||||
if(has_set_repeat)
|
||||
if(g_has_set_repeat)
|
||||
{
|
||||
std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
repeat = atoi(argv[i]+1);
|
||||
has_set_repeat = true;
|
||||
if(repeat <= 0)
|
||||
{
|
||||
std::cout << "Invalid \'repeat\' value " << argv[i]+1 << std::endl;
|
||||
return 1;
|
||||
}
|
||||
set_repeat_from_string(argv[i]+1);
|
||||
}
|
||||
else if(argv[i][0] == 's')
|
||||
{
|
||||
if(has_set_seed)
|
||||
if(g_has_set_seed)
|
||||
{
|
||||
std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
seed = int(strtoul(argv[i]+1, 0, 10));
|
||||
has_set_seed = true;
|
||||
bool ok = seed!=0;
|
||||
if(!ok)
|
||||
{
|
||||
std::cout << "Invalid \'seed\' value " << argv[i]+1 << std::endl;
|
||||
return 1;
|
||||
}
|
||||
set_seed_from_string(argv[i]+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -429,22 +462,29 @@ int main(int argc, char *argv[])
|
||||
std::cout << "This test application takes the following optional arguments:" << std::endl;
|
||||
std::cout << " rN Repeat each test N times (default: " << DEFAULT_REPEAT << ")" << std::endl;
|
||||
std::cout << " sN Use N as seed for random numbers (default: based on current time)" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "If defined, the environment variables EIGEN_REPEAT and EIGEN_SEED" << std::endl;
|
||||
std::cout << "will be used as default values for these parameters." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!has_set_seed) seed = (unsigned int) time(NULL);
|
||||
if(!has_set_repeat) repeat = DEFAULT_REPEAT;
|
||||
char *env_EIGEN_REPEAT = getenv("EIGEN_REPEAT");
|
||||
if(!g_has_set_repeat && env_EIGEN_REPEAT)
|
||||
set_repeat_from_string(env_EIGEN_REPEAT);
|
||||
char *env_EIGEN_SEED = getenv("EIGEN_SEED");
|
||||
if(!g_has_set_seed && env_EIGEN_SEED)
|
||||
set_seed_from_string(env_EIGEN_SEED);
|
||||
|
||||
std::cout << "Initializing random number generator with seed " << seed << std::endl;
|
||||
srand(seed);
|
||||
std::cout << "Repeating each test " << repeat << " times" << std::endl;
|
||||
if(!g_has_set_seed) g_seed = (unsigned int) time(NULL);
|
||||
if(!g_has_set_repeat) g_repeat = DEFAULT_REPEAT;
|
||||
|
||||
std::cout << "Initializing random number generator with seed " << g_seed << std::endl;
|
||||
srand(g_seed);
|
||||
std::cout << "Repeating each test " << g_repeat << " times" << std::endl;
|
||||
|
||||
Eigen::g_repeat = repeat;
|
||||
Eigen::g_test_stack.push_back(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC));
|
||||
|
||||
EIGEN_CAT(test_,EIGEN_TEST_FUNC)();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -66,12 +66,45 @@ template<typename MatrixType> void permutationmatrices(const MatrixType& m)
|
||||
|
||||
for (int i=0; i<rows; i++)
|
||||
for (int j=0; j<cols; j++)
|
||||
VERIFY_IS_APPROX(m_original(lv(i),j), m_permuted(i,rv(j)));
|
||||
VERIFY_IS_APPROX(m_permuted(lv(i),j), m_original(i,rv(j)));
|
||||
|
||||
Matrix<Scalar,Rows,Rows> lm(lp);
|
||||
Matrix<Scalar,Cols,Cols> rm(rp);
|
||||
|
||||
VERIFY_IS_APPROX(m_permuted, lm*m_original*rm);
|
||||
|
||||
VERIFY_IS_APPROX(lp.inverse()*m_permuted*rp.inverse(), m_original);
|
||||
VERIFY((lp*lp.inverse()).toDenseMatrix().isIdentity());
|
||||
|
||||
LeftPermutationVectorType lv2;
|
||||
randomPermutationVector(lv2, rows);
|
||||
LeftPermutationType lp2(lv2);
|
||||
Matrix<Scalar,Rows,Rows> lm2(lp2);
|
||||
VERIFY_IS_APPROX((lp*lp2).toDenseMatrix().template cast<Scalar>(), lm*lm2);
|
||||
|
||||
LeftPermutationType identityp;
|
||||
identityp.setIdentity(rows);
|
||||
VERIFY_IS_APPROX(m_original, identityp*m_original);
|
||||
|
||||
if(rows>1 && cols>1)
|
||||
{
|
||||
lp2 = lp;
|
||||
int i = ei_random<int>(0, rows-1);
|
||||
int j;
|
||||
do j = ei_random<int>(0, rows-1); while(j==i);
|
||||
lp2.applyTranspositionOnTheLeft(i, j);
|
||||
lm = lp;
|
||||
lm.row(i).swap(lm.row(j));
|
||||
VERIFY_IS_APPROX(lm, lp2.toDenseMatrix().template cast<Scalar>());
|
||||
|
||||
RightPermutationType rp2 = rp;
|
||||
i = ei_random<int>(0, cols-1);
|
||||
do j = ei_random<int>(0, cols-1); while(j==i);
|
||||
rp2.applyTranspositionOnTheRight(i, j);
|
||||
rm = rp;
|
||||
rm.col(i).swap(rm.col(j));
|
||||
VERIFY_IS_APPROX(rm, rp2.toDenseMatrix().template cast<Scalar>());
|
||||
}
|
||||
}
|
||||
|
||||
void test_permutationmatrices()
|
||||
|
||||
80
test/prec_inverse_4x4.cpp
Normal file
80
test/prec_inverse_4x4.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// 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"
|
||||
#include <Eigen/LU>
|
||||
#include <algorithm>
|
||||
|
||||
template<typename MatrixType> void inverse_permutation_4x4()
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
Vector4i indices(0,1,2,3);
|
||||
for(int i = 0; i < 24; ++i)
|
||||
{
|
||||
MatrixType m = PermutationMatrix<4>(indices);
|
||||
MatrixType inv = m.inverse();
|
||||
double error = double( (m*inv-MatrixType::Identity()).norm() / epsilon<Scalar>() );
|
||||
VERIFY(error == 0.0);
|
||||
std::next_permutation(indices.data(),indices.data()+4);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatrixType> void inverse_general_4x4(int repeat)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
double error_sum = 0., error_max = 0.;
|
||||
for(int i = 0; i < repeat; ++i)
|
||||
{
|
||||
MatrixType m;
|
||||
RealScalar absdet;
|
||||
do {
|
||||
m = MatrixType::Random();
|
||||
absdet = ei_abs(m.determinant());
|
||||
} while(absdet < epsilon<Scalar>());
|
||||
MatrixType inv = m.inverse();
|
||||
double error = double( (m*inv-MatrixType::Identity()).norm() * absdet / epsilon<Scalar>() );
|
||||
error_sum += error;
|
||||
error_max = std::max(error_max, error);
|
||||
}
|
||||
std::cerr << "inverse_general_4x4, Scalar = " << type_name<Scalar>() << std::endl;
|
||||
double error_avg = error_sum / repeat;
|
||||
EIGEN_DEBUG_VAR(error_avg);
|
||||
EIGEN_DEBUG_VAR(error_max);
|
||||
VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.0));
|
||||
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
|
||||
}
|
||||
|
||||
void test_prec_inverse_4x4()
|
||||
{
|
||||
CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>()));
|
||||
CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
|
||||
|
||||
CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
|
||||
CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
|
||||
|
||||
CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>()));
|
||||
CALL_SUBTEST_3((inverse_general_4x4<Matrix4cf>(50000 * g_repeat)));
|
||||
}
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <Eigen/QR>
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
bool areNotApprox(const MatrixBase<Derived1>& m1, const MatrixBase<Derived2>& m2, typename Derived1::RealScalar epsilon = precision<typename Derived1::RealScalar>())
|
||||
bool areNotApprox(const MatrixBase<Derived1>& m1, const MatrixBase<Derived2>& m2, typename Derived1::RealScalar epsilon = dummy_precision<typename Derived1::RealScalar>())
|
||||
{
|
||||
return !((m1-m2).cwiseAbs2().maxCoeff() < epsilon * epsilon
|
||||
* std::max(m1.cwiseAbs2().maxCoeff(), m2.cwiseAbs2().maxCoeff()));
|
||||
|
||||
@@ -55,15 +55,15 @@ template<typename MatrixType> void product_selfadjoint(const MatrixType& m)
|
||||
// rank2 update
|
||||
m2 = m1.template triangularView<LowerTriangular>();
|
||||
m2.template selfadjointView<LowerTriangular>().rankUpdate(v1,v2);
|
||||
VERIFY_IS_APPROX(m2, (m1 + v1 * v2.adjoint()+ v2 * v1.adjoint()).template triangularView<LowerTriangular>().toDense());
|
||||
VERIFY_IS_APPROX(m2, (m1 + v1 * v2.adjoint()+ v2 * v1.adjoint()).template triangularView<LowerTriangular>().toDenseMatrix());
|
||||
|
||||
m2 = m1.template triangularView<UpperTriangular>();
|
||||
m2.template selfadjointView<UpperTriangular>().rankUpdate(-v1,s2*v2,s3);
|
||||
VERIFY_IS_APPROX(m2, (m1 + (-s2*s3) * (v1 * v2.adjoint()+ v2 * v1.adjoint())).template triangularView<UpperTriangular>().toDense());
|
||||
VERIFY_IS_APPROX(m2, (m1 + (-s2*s3) * (v1 * v2.adjoint()+ v2 * v1.adjoint())).template triangularView<UpperTriangular>().toDenseMatrix());
|
||||
|
||||
m2 = m1.template triangularView<UpperTriangular>();
|
||||
m2.template selfadjointView<UpperTriangular>().rankUpdate(-r1.adjoint(),r2.adjoint()*s3,s1);
|
||||
VERIFY_IS_APPROX(m2, (m1 + (-s3*s1) * (r1.adjoint() * r2 + r2.adjoint() * r1)).template triangularView<UpperTriangular>().toDense());
|
||||
VERIFY_IS_APPROX(m2, (m1 + (-s3*s1) * (r1.adjoint() * r2 + r2.adjoint() * r1)).template triangularView<UpperTriangular>().toDenseMatrix());
|
||||
|
||||
if (rows>1)
|
||||
{
|
||||
@@ -71,7 +71,7 @@ template<typename MatrixType> void product_selfadjoint(const MatrixType& m)
|
||||
m2.block(1,1,rows-1,cols-1).template selfadjointView<LowerTriangular>().rankUpdate(v1.end(rows-1),v2.start(cols-1));
|
||||
m3 = m1;
|
||||
m3.block(1,1,rows-1,cols-1) += v1.end(rows-1) * v2.start(cols-1).adjoint()+ v2.start(cols-1) * v1.end(rows-1).adjoint();
|
||||
VERIFY_IS_APPROX(m2, m3.template triangularView<LowerTriangular>().toDense());
|
||||
VERIFY_IS_APPROX(m2, m3.template triangularView<LowerTriangular>().toDenseMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,27 +46,27 @@ template<typename MatrixType> void syrk(const MatrixType& m)
|
||||
|
||||
m2.setZero();
|
||||
VERIFY_IS_APPROX((m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs2,s1)._expression()),
|
||||
((s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<LowerTriangular>().toDense()));
|
||||
((s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<LowerTriangular>().toDenseMatrix()));
|
||||
|
||||
m2.setZero();
|
||||
VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs2,s1)._expression(),
|
||||
(s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<UpperTriangular>().toDense());
|
||||
(s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<UpperTriangular>().toDenseMatrix());
|
||||
|
||||
m2.setZero();
|
||||
VERIFY_IS_APPROX(m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs1.adjoint(),s1)._expression(),
|
||||
(s1 * rhs1.adjoint() * rhs1).eval().template triangularView<LowerTriangular>().toDense());
|
||||
(s1 * rhs1.adjoint() * rhs1).eval().template triangularView<LowerTriangular>().toDenseMatrix());
|
||||
|
||||
m2.setZero();
|
||||
VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs1.adjoint(),s1)._expression(),
|
||||
(s1 * rhs1.adjoint() * rhs1).eval().template triangularView<UpperTriangular>().toDense());
|
||||
(s1 * rhs1.adjoint() * rhs1).eval().template triangularView<UpperTriangular>().toDenseMatrix());
|
||||
|
||||
m2.setZero();
|
||||
VERIFY_IS_APPROX(m2.template selfadjointView<LowerTriangular>().rankUpdate(rhs3.adjoint(),s1)._expression(),
|
||||
(s1 * rhs3.adjoint() * rhs3).eval().template triangularView<LowerTriangular>().toDense());
|
||||
(s1 * rhs3.adjoint() * rhs3).eval().template triangularView<LowerTriangular>().toDenseMatrix());
|
||||
|
||||
m2.setZero();
|
||||
VERIFY_IS_APPROX(m2.template selfadjointView<UpperTriangular>().rankUpdate(rhs3.adjoint(),s1)._expression(),
|
||||
(s1 * rhs3.adjoint() * rhs3).eval().template triangularView<UpperTriangular>().toDense());
|
||||
(s1 * rhs3.adjoint() * rhs3).eval().template triangularView<UpperTriangular>().toDenseMatrix());
|
||||
}
|
||||
|
||||
void test_product_syrk()
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define VERIFY_TRSM(TRI,XB) { \
|
||||
(XB).setRandom(); ref = (XB); \
|
||||
(TRI).solveInPlace(XB); \
|
||||
VERIFY_IS_APPROX((TRI).toDense() * (XB), ref); \
|
||||
VERIFY_IS_APPROX((TRI).toDenseMatrix() * (XB), ref); \
|
||||
}
|
||||
|
||||
template<typename Scalar> void trsm(int size,int cols)
|
||||
|
||||
10
test/qr.cpp
10
test/qr.cpp
@@ -38,13 +38,13 @@ template<typename MatrixType> void qr(const MatrixType& m)
|
||||
HouseholderQR<MatrixType> qrOfA(a);
|
||||
MatrixType r = qrOfA.matrixQR();
|
||||
|
||||
MatrixQType q = qrOfA.matrixQ();
|
||||
MatrixQType q = qrOfA.householderQ();
|
||||
VERIFY_IS_UNITARY(q);
|
||||
|
||||
// FIXME need better way to construct trapezoid
|
||||
for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) if(i>j) r(i,j) = Scalar(0);
|
||||
|
||||
VERIFY_IS_APPROX(a, qrOfA.matrixQ() * r);
|
||||
VERIFY_IS_APPROX(a, qrOfA.householderQ() * r);
|
||||
}
|
||||
|
||||
template<typename MatrixType, int Cols2> void qr_fixedsize()
|
||||
@@ -58,7 +58,7 @@ template<typename MatrixType, int Cols2> void qr_fixedsize()
|
||||
// FIXME need better way to construct trapezoid
|
||||
for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0);
|
||||
|
||||
VERIFY_IS_APPROX(m1, qr.matrixQ() * r);
|
||||
VERIFY_IS_APPROX(m1, qr.householderQ() * r);
|
||||
|
||||
Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
|
||||
Matrix<Scalar,Rows,Cols2> m3 = m1*m2;
|
||||
@@ -93,7 +93,7 @@ template<typename MatrixType> void qr_invertible()
|
||||
m1.setZero();
|
||||
for(int i = 0; i < size; i++) m1(i,i) = ei_random<Scalar>();
|
||||
RealScalar absdet = ei_abs(m1.diagonal().prod());
|
||||
m3 = qr.matrixQ(); // get a unitary
|
||||
m3 = qr.householderQ(); // get a unitary
|
||||
m1 = m3 * m1 * m3;
|
||||
qr.compute(m1);
|
||||
VERIFY_IS_APPROX(absdet, qr.absDeterminant());
|
||||
@@ -107,7 +107,7 @@ template<typename MatrixType> void qr_verify_assert()
|
||||
HouseholderQR<MatrixType> qr;
|
||||
VERIFY_RAISES_ASSERT(qr.matrixQR())
|
||||
VERIFY_RAISES_ASSERT(qr.solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(qr.matrixQ())
|
||||
VERIFY_RAISES_ASSERT(qr.householderQ())
|
||||
VERIFY_RAISES_ASSERT(qr.absDeterminant())
|
||||
VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
|
||||
}
|
||||
|
||||
@@ -28,10 +28,11 @@
|
||||
|
||||
template<typename MatrixType> void qr()
|
||||
{
|
||||
int rows = ei_random<int>(20,200), cols = ei_random<int>(20,200), cols2 = ei_random<int>(20,200);
|
||||
int rows = ei_random<int>(2,200), cols = ei_random<int>(2,200), cols2 = ei_random<int>(2,200);
|
||||
int rank = ei_random<int>(1, std::min(rows, cols)-1);
|
||||
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename MatrixType::RealScalar RealScalar;
|
||||
typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
|
||||
typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
|
||||
MatrixType m1;
|
||||
@@ -43,19 +44,11 @@ template<typename MatrixType> void qr()
|
||||
VERIFY(!qr.isInvertible());
|
||||
VERIFY(!qr.isSurjective());
|
||||
|
||||
MatrixType r = qr.matrixQR();
|
||||
|
||||
MatrixQType q = qr.matrixQ();
|
||||
MatrixQType q = qr.householderQ();
|
||||
VERIFY_IS_UNITARY(q);
|
||||
|
||||
// FIXME need better way to construct trapezoid
|
||||
for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) if(i>j) r(i,j) = Scalar(0);
|
||||
|
||||
MatrixType b = qr.matrixQ() * r;
|
||||
|
||||
MatrixType c = MatrixType::Zero(rows,cols);
|
||||
|
||||
for(int i = 0; i < cols; ++i) c.col(qr.colsPermutation().coeff(i)) = b.col(i);
|
||||
MatrixType r = qr.matrixQR().template triangularView<UpperTriangular>();
|
||||
MatrixType c = q * r * qr.colsPermutation().inverse();
|
||||
VERIFY_IS_APPROX(m1, c);
|
||||
|
||||
MatrixType m2 = MatrixType::Random(cols,cols2);
|
||||
@@ -79,15 +72,8 @@ template<typename MatrixType, int Cols2> void qr_fixedsize()
|
||||
VERIFY(!qr.isInvertible());
|
||||
VERIFY(!qr.isSurjective());
|
||||
|
||||
Matrix<Scalar,Rows,Cols> r = qr.matrixQR();
|
||||
// FIXME need better way to construct trapezoid
|
||||
for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0);
|
||||
|
||||
Matrix<Scalar,Rows,Cols> b = qr.matrixQ() * r;
|
||||
|
||||
Matrix<Scalar,Rows,Cols> c = MatrixType::Zero(Rows,Cols);
|
||||
|
||||
for(int i = 0; i < Cols; ++i) c.col(qr.colsPermutation().coeff(i)) = b.col(i);
|
||||
Matrix<Scalar,Rows,Cols> r = qr.matrixQR().template triangularView<UpperTriangular>();
|
||||
Matrix<Scalar,Rows,Cols> c = qr.householderQ() * r * qr.colsPermutation().inverse();
|
||||
VERIFY_IS_APPROX(m1, c);
|
||||
|
||||
Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
|
||||
@@ -117,13 +103,13 @@ template<typename MatrixType> void qr_invertible()
|
||||
ColPivHouseholderQR<MatrixType> qr(m1);
|
||||
m3 = MatrixType::Random(size,size);
|
||||
m2 = qr.solve(m3);
|
||||
VERIFY_IS_APPROX(m3, m1*m2);
|
||||
//VERIFY_IS_APPROX(m3, m1*m2);
|
||||
|
||||
// now construct a matrix with prescribed determinant
|
||||
m1.setZero();
|
||||
for(int i = 0; i < size; i++) m1(i,i) = ei_random<Scalar>();
|
||||
RealScalar absdet = ei_abs(m1.diagonal().prod());
|
||||
m3 = qr.matrixQ(); // get a unitary
|
||||
m3 = qr.householderQ(); // get a unitary
|
||||
m1 = m3 * m1 * m3;
|
||||
qr.compute(m1);
|
||||
VERIFY_IS_APPROX(absdet, qr.absDeterminant());
|
||||
@@ -137,7 +123,7 @@ template<typename MatrixType> void qr_verify_assert()
|
||||
ColPivHouseholderQR<MatrixType> qr;
|
||||
VERIFY_RAISES_ASSERT(qr.matrixQR())
|
||||
VERIFY_RAISES_ASSERT(qr.solve(tmp))
|
||||
VERIFY_RAISES_ASSERT(qr.matrixQ())
|
||||
VERIFY_RAISES_ASSERT(qr.householderQ())
|
||||
VERIFY_RAISES_ASSERT(qr.dimensionOfKernel())
|
||||
VERIFY_RAISES_ASSERT(qr.isInjective())
|
||||
VERIFY_RAISES_ASSERT(qr.isSurjective())
|
||||
@@ -149,7 +135,7 @@ template<typename MatrixType> void qr_verify_assert()
|
||||
|
||||
void test_qr_colpivoting()
|
||||
{
|
||||
for(int i = 0; i < 1; i++) {
|
||||
for(int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1( qr<MatrixXf>() );
|
||||
CALL_SUBTEST_2( qr<MatrixXd>() );
|
||||
CALL_SUBTEST_3( qr<MatrixXcd>() );
|
||||
|
||||
@@ -51,11 +51,8 @@ template<typename MatrixType> void qr()
|
||||
// FIXME need better way to construct trapezoid
|
||||
for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) if(i>j) r(i,j) = Scalar(0);
|
||||
|
||||
MatrixType b = qr.matrixQ() * r;
|
||||
MatrixType c = qr.matrixQ() * r * qr.colsPermutation().inverse();
|
||||
|
||||
MatrixType c = MatrixType::Zero(rows,cols);
|
||||
|
||||
for(int i = 0; i < cols; ++i) c.col(qr.colsPermutation().coeff(i)) = b.col(i);
|
||||
VERIFY_IS_APPROX(m1, c);
|
||||
|
||||
MatrixType m2 = MatrixType::Random(cols,cols2);
|
||||
|
||||
@@ -9,7 +9,7 @@ magenta='\E[35m'
|
||||
cyan='\E[36m'
|
||||
white='\E[37m'
|
||||
|
||||
if ! ./test_$1 > /dev/null 2> .runtest.log ; then
|
||||
if ! ./$1 > /dev/null 2> .runtest.log ; then
|
||||
echo -e $red Test $1 failed: $black
|
||||
echo -e $blue
|
||||
cat .runtest.log
|
||||
|
||||
@@ -34,7 +34,7 @@ bool test_random_setter(SparseMatrix<Scalar,Options>& sm, const DenseType& ref,
|
||||
std::vector<Vector2i> remaining = nonzeroCoords;
|
||||
while(!remaining.empty())
|
||||
{
|
||||
int i = ei_random<int>(0,remaining.size()-1);
|
||||
int i = ei_random<int>(0,static_cast<int>(remaining.size())-1);
|
||||
w(remaining[i].x(),remaining[i].y()) = ref.coeff(remaining[i].x(),remaining[i].y());
|
||||
remaining[i] = remaining.back();
|
||||
remaining.pop_back();
|
||||
@@ -50,7 +50,7 @@ bool test_random_setter(DynamicSparseMatrix<T>& sm, const DenseType& ref, const
|
||||
std::vector<Vector2i> remaining = nonzeroCoords;
|
||||
while(!remaining.empty())
|
||||
{
|
||||
int i = ei_random<int>(0,remaining.size()-1);
|
||||
int i = ei_random<int>(0,static_cast<int>(remaining.size())-1);
|
||||
sm.coeffRef(remaining[i].x(),remaining[i].y()) = ref.coeff(remaining[i].x(),remaining[i].y());
|
||||
remaining[i] = remaining.back();
|
||||
remaining.pop_back();
|
||||
|
||||
@@ -79,6 +79,14 @@ template<typename MatrixType> void stable_norm(const MatrixType& m)
|
||||
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);
|
||||
|
||||
// Test compilation of cwise() version
|
||||
VERIFY_IS_APPROX(vrand.colwise().stableNorm(), vrand.colwise().norm());
|
||||
VERIFY_IS_APPROX(vrand.colwise().blueNorm(), vrand.colwise().norm());
|
||||
VERIFY_IS_APPROX(vrand.colwise().hypotNorm(), vrand.colwise().norm());
|
||||
VERIFY_IS_APPROX(vrand.rowwise().stableNorm(), vrand.rowwise().norm());
|
||||
VERIFY_IS_APPROX(vrand.rowwise().blueNorm(), vrand.rowwise().norm());
|
||||
VERIFY_IS_APPROX(vrand.rowwise().hypotNorm(), vrand.rowwise().norm());
|
||||
}
|
||||
|
||||
void test_stable_norm()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Usage:
|
||||
# - create a new folder, let's call it cdash
|
||||
# - in that folder, do:
|
||||
# ctest -S path/to/eigen2/test/testsuite.cmake[,option1=value1[,option2=value2]]
|
||||
# ctest -S path/to/eigen/test/testsuite.cmake[,option1=value1[,option2=value2]]
|
||||
#
|
||||
# Options:
|
||||
# - EIGEN_CXX: compiler, eg.: g++-4.2
|
||||
@@ -44,9 +44,9 @@
|
||||
# ARCH=`uname -m`
|
||||
# SITE=`hostname`
|
||||
# VERSION=opensuse-11.1
|
||||
# WORK_DIR=/home/gael/Coding/eigen2/cdash
|
||||
# WORK_DIR=/home/gael/Coding/eigen/cdash
|
||||
# # get the last version of the script
|
||||
# wget http://bitbucket.org/eigen/eigen2/raw/tip/test/testsuite.cmake -o $WORK_DIR/testsuite.cmake
|
||||
# wget http://bitbucket.org/eigen/eigen/raw/tip/test/testsuite.cmake -o $WORK_DIR/testsuite.cmake
|
||||
# COMMON="ctest -S $WORK_DIR/testsuite.cmake,EIGEN_WORK_DIR=$WORK_DIR,EIGEN_SITE=$SITE,EIGEN_MODE=$1,EIGEN_BUILD_STRING=$OS_VERSION-$ARCH"
|
||||
# $COMMON-gcc-3.4.6,EIGEN_CXX=g++-3.4
|
||||
# $COMMON-gcc-4.0.1,EIGEN_CXX=g++-4.0.1
|
||||
@@ -141,7 +141,7 @@ endif(NOT EIGEN_MODE)
|
||||
|
||||
if(NOT EIGEN_NO_UPDATE)
|
||||
SET (CTEST_CVS_COMMAND "hg")
|
||||
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone http://bitbucket.org/eigen/eigen2 \"${CTEST_SOURCE_DIRECTORY}\"")
|
||||
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone http://bitbucket.org/eigen/eigen \"${CTEST_SOURCE_DIRECTORY}\"")
|
||||
SET(CTEST_BACKUP_AND_RESTORE TRUE) # the backup is CVS related ...
|
||||
endif(NOT EIGEN_NO_UPDATE)
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
#include "main.h"
|
||||
|
||||
template<typename MatrixType> void triangular(const MatrixType& m)
|
||||
|
||||
|
||||
template<typename MatrixType> void triangular_square(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
@@ -51,8 +53,8 @@ template<typename MatrixType> void triangular(const MatrixType& m)
|
||||
v2 = VectorType::Random(rows),
|
||||
vzero = VectorType::Zero(rows);
|
||||
|
||||
MatrixType m1up = m1.template triangularView<Eigen::UpperTriangular>();
|
||||
MatrixType m2up = m2.template triangularView<Eigen::UpperTriangular>();
|
||||
MatrixType m1up = m1.template triangularView<UpperTriangular>();
|
||||
MatrixType m2up = m2.template triangularView<UpperTriangular>();
|
||||
|
||||
if (rows*cols>1)
|
||||
{
|
||||
@@ -66,83 +68,197 @@ template<typename MatrixType> void triangular(const MatrixType& m)
|
||||
// test overloaded operator+=
|
||||
r1.setZero();
|
||||
r2.setZero();
|
||||
r1.template triangularView<Eigen::UpperTriangular>() += m1;
|
||||
r1.template triangularView<UpperTriangular>() += m1;
|
||||
r2 += m1up;
|
||||
VERIFY_IS_APPROX(r1,r2);
|
||||
|
||||
// test overloaded operator=
|
||||
m1.setZero();
|
||||
m1.template triangularView<Eigen::UpperTriangular>() = m2.transpose() + m2;
|
||||
m1.template triangularView<UpperTriangular>() = m2.transpose() + m2;
|
||||
m3 = m2.transpose() + m2;
|
||||
VERIFY_IS_APPROX(m3.template triangularView<Eigen::LowerTriangular>().transpose().toDense(), m1);
|
||||
VERIFY_IS_APPROX(m3.template triangularView<LowerTriangular>().transpose().toDenseMatrix(), m1);
|
||||
|
||||
// test overloaded operator=
|
||||
m1.setZero();
|
||||
m1.template triangularView<Eigen::LowerTriangular>() = m2.transpose() + m2;
|
||||
VERIFY_IS_APPROX(m3.template triangularView<Eigen::LowerTriangular>().toDense(), m1);
|
||||
m1.template triangularView<LowerTriangular>() = m2.transpose() + m2;
|
||||
VERIFY_IS_APPROX(m3.template triangularView<LowerTriangular>().toDenseMatrix(), m1);
|
||||
|
||||
m1 = MatrixType::Random(rows, cols);
|
||||
for (int i=0; i<rows; ++i)
|
||||
while (ei_abs2(m1(i,i))<1e-3) m1(i,i) = ei_random<Scalar>();
|
||||
while (ei_abs2(m1(i,i))<1e-1) m1(i,i) = ei_random<Scalar>();
|
||||
|
||||
Transpose<MatrixType> trm4(m4);
|
||||
// test back and forward subsitution with a vector as the rhs
|
||||
m3 = m1.template triangularView<Eigen::UpperTriangular>();
|
||||
VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Eigen::LowerTriangular>().solve(v2)), largerEps));
|
||||
m3 = m1.template triangularView<Eigen::LowerTriangular>();
|
||||
VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Eigen::UpperTriangular>().solve(v2)), largerEps));
|
||||
m3 = m1.template triangularView<Eigen::UpperTriangular>();
|
||||
VERIFY(v2.isApprox(m3 * (m1.template triangularView<Eigen::UpperTriangular>().solve(v2)), largerEps));
|
||||
m3 = m1.template triangularView<Eigen::LowerTriangular>();
|
||||
VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Eigen::LowerTriangular>().solve(v2)), largerEps));
|
||||
m3 = m1.template triangularView<UpperTriangular>();
|
||||
VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<LowerTriangular>().solve(v2)), largerEps));
|
||||
m3 = m1.template triangularView<LowerTriangular>();
|
||||
VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<UpperTriangular>().solve(v2)), largerEps));
|
||||
m3 = m1.template triangularView<UpperTriangular>();
|
||||
VERIFY(v2.isApprox(m3 * (m1.template triangularView<UpperTriangular>().solve(v2)), largerEps));
|
||||
m3 = m1.template triangularView<LowerTriangular>();
|
||||
VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<LowerTriangular>().solve(v2)), largerEps));
|
||||
|
||||
// test back and forward subsitution with a matrix as the rhs
|
||||
m3 = m1.template triangularView<Eigen::UpperTriangular>();
|
||||
VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Eigen::LowerTriangular>().solve(m2)), largerEps));
|
||||
m3 = m1.template triangularView<Eigen::LowerTriangular>();
|
||||
VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Eigen::UpperTriangular>().solve(m2)), largerEps));
|
||||
m3 = m1.template triangularView<Eigen::UpperTriangular>();
|
||||
VERIFY(m2.isApprox(m3 * (m1.template triangularView<Eigen::UpperTriangular>().solve(m2)), largerEps));
|
||||
m3 = m1.template triangularView<Eigen::LowerTriangular>();
|
||||
VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Eigen::LowerTriangular>().solve(m2)), largerEps));
|
||||
m3 = m1.template triangularView<UpperTriangular>();
|
||||
VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<LowerTriangular>().solve(m2)), largerEps));
|
||||
m3 = m1.template triangularView<LowerTriangular>();
|
||||
VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<UpperTriangular>().solve(m2)), largerEps));
|
||||
m3 = m1.template triangularView<UpperTriangular>();
|
||||
VERIFY(m2.isApprox(m3 * (m1.template triangularView<UpperTriangular>().solve(m2)), largerEps));
|
||||
m3 = m1.template triangularView<LowerTriangular>();
|
||||
VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<LowerTriangular>().solve(m2)), largerEps));
|
||||
|
||||
// check M * inv(L) using in place API
|
||||
m4 = m3;
|
||||
<<<<<<< local
|
||||
m3.transpose().template triangularView<Eigen::UpperTriangular>().solveInPlace(trm4);
|
||||
VERIFY(m4.cwiseAbs().isIdentity(test_precision<RealScalar>()));
|
||||
=======
|
||||
m3.transpose().template triangularView<UpperTriangular>().solveInPlace(trm4);
|
||||
VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>()));
|
||||
>>>>>>> other
|
||||
|
||||
// check M * inv(U) using in place API
|
||||
m3 = m1.template triangularView<Eigen::UpperTriangular>();
|
||||
m3 = m1.template triangularView<UpperTriangular>();
|
||||
m4 = m3;
|
||||
<<<<<<< local
|
||||
m3.transpose().template triangularView<Eigen::LowerTriangular>().solveInPlace(trm4);
|
||||
VERIFY(m4.cwiseAbs().isIdentity(test_precision<RealScalar>()));
|
||||
=======
|
||||
m3.transpose().template triangularView<LowerTriangular>().solveInPlace(trm4);
|
||||
VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>()));
|
||||
>>>>>>> other
|
||||
|
||||
// check solve with unit diagonal
|
||||
m3 = m1.template triangularView<Eigen::UnitUpperTriangular>();
|
||||
VERIFY(m2.isApprox(m3 * (m1.template triangularView<Eigen::UnitUpperTriangular>().solve(m2)), largerEps));
|
||||
m3 = m1.template triangularView<UnitUpperTriangular>();
|
||||
VERIFY(m2.isApprox(m3 * (m1.template triangularView<UnitUpperTriangular>().solve(m2)), largerEps));
|
||||
|
||||
// VERIFY(( m1.template triangularView<Eigen::UpperTriangular>()
|
||||
// * m2.template triangularView<Eigen::UpperTriangular>()).isUpperTriangular());
|
||||
// VERIFY(( m1.template triangularView<UpperTriangular>()
|
||||
// * m2.template triangularView<UpperTriangular>()).isUpperTriangular());
|
||||
|
||||
// test swap
|
||||
m1.setOnes();
|
||||
m2.setZero();
|
||||
m2.template triangularView<Eigen::UpperTriangular>().swap(m1);
|
||||
m2.template triangularView<UpperTriangular>().swap(m1);
|
||||
m3.setZero();
|
||||
m3.template triangularView<Eigen::UpperTriangular>().setOnes();
|
||||
m3.template triangularView<UpperTriangular>().setOnes();
|
||||
VERIFY_IS_APPROX(m2,m3);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename MatrixType> void triangular_rect(const MatrixType& m)
|
||||
{
|
||||
typedef typename MatrixType::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
|
||||
typedef Matrix<Scalar, Rows, 1> VectorType;
|
||||
typedef Matrix<Scalar, Rows, Rows> RMatrixType;
|
||||
|
||||
|
||||
int rows = m.rows();
|
||||
int cols = m.cols();
|
||||
|
||||
MatrixType m1 = MatrixType::Random(rows, cols),
|
||||
m2 = MatrixType::Random(rows, cols),
|
||||
m3(rows, cols),
|
||||
m4(rows, cols),
|
||||
r1(rows, cols),
|
||||
r2(rows, cols),
|
||||
mzero = MatrixType::Zero(rows, cols),
|
||||
mones = MatrixType::Ones(rows, cols);
|
||||
RMatrixType identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
|
||||
::Identity(rows, rows),
|
||||
square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
|
||||
::Random(rows, rows);
|
||||
VectorType v1 = VectorType::Random(rows),
|
||||
v2 = VectorType::Random(rows),
|
||||
vzero = VectorType::Zero(rows);
|
||||
|
||||
MatrixType m1up = m1.template triangularView<UpperTriangular>();
|
||||
MatrixType m2up = m2.template triangularView<UpperTriangular>();
|
||||
|
||||
if (rows*cols>1)
|
||||
{
|
||||
VERIFY(m1up.isUpperTriangular());
|
||||
VERIFY(m2up.transpose().isLowerTriangular());
|
||||
VERIFY(!m2.isLowerTriangular());
|
||||
}
|
||||
|
||||
// test overloaded operator+=
|
||||
r1.setZero();
|
||||
r2.setZero();
|
||||
r1.template triangularView<UpperTriangular>() += m1;
|
||||
r2 += m1up;
|
||||
VERIFY_IS_APPROX(r1,r2);
|
||||
|
||||
// test overloaded operator=
|
||||
m1.setZero();
|
||||
m1.template triangularView<UpperTriangular>() = 3 * m2;
|
||||
m3 = 3 * m2;
|
||||
VERIFY_IS_APPROX(m3.template triangularView<UpperTriangular>().toDenseMatrix(), m1);
|
||||
|
||||
|
||||
m1.setZero();
|
||||
m1.template triangularView<LowerTriangular>() = 3 * m2;
|
||||
VERIFY_IS_APPROX(m3.template triangularView<LowerTriangular>().toDenseMatrix(), m1);
|
||||
|
||||
m1.setZero();
|
||||
m1.template triangularView<StrictlyUpperTriangular>() = 3 * m2;
|
||||
VERIFY_IS_APPROX(m3.template triangularView<StrictlyUpperTriangular>().toDenseMatrix(), m1);
|
||||
|
||||
|
||||
m1.setZero();
|
||||
m1.template triangularView<StrictlyLowerTriangular>() = 3 * m2;
|
||||
VERIFY_IS_APPROX(m3.template triangularView<StrictlyLowerTriangular>().toDenseMatrix(), m1);
|
||||
m1.setRandom();
|
||||
m2 = m1.template triangularView<UpperTriangular>();
|
||||
VERIFY(m2.isUpperTriangular());
|
||||
VERIFY(!m2.isLowerTriangular());
|
||||
m2 = m1.template triangularView<StrictlyUpperTriangular>();
|
||||
VERIFY(m2.isUpperTriangular());
|
||||
VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
|
||||
m2 = m1.template triangularView<UnitUpperTriangular>();
|
||||
VERIFY(m2.isUpperTriangular());
|
||||
m2.diagonal().cwise() -= Scalar(1);
|
||||
VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
|
||||
m2 = m1.template triangularView<LowerTriangular>();
|
||||
VERIFY(m2.isLowerTriangular());
|
||||
VERIFY(!m2.isUpperTriangular());
|
||||
m2 = m1.template triangularView<StrictlyLowerTriangular>();
|
||||
VERIFY(m2.isLowerTriangular());
|
||||
VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
|
||||
m2 = m1.template triangularView<UnitLowerTriangular>();
|
||||
VERIFY(m2.isLowerTriangular());
|
||||
m2.diagonal().cwise() -= Scalar(1);
|
||||
VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
|
||||
// test swap
|
||||
m1.setOnes();
|
||||
m2.setZero();
|
||||
m2.template triangularView<UpperTriangular>().swap(m1);
|
||||
m3.setZero();
|
||||
m3.template triangularView<UpperTriangular>().setOnes();
|
||||
VERIFY_IS_APPROX(m2,m3);
|
||||
}
|
||||
|
||||
void test_triangular()
|
||||
{
|
||||
for(int i = 0; i < g_repeat ; i++) {
|
||||
CALL_SUBTEST_1( triangular(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( triangular(Matrix<float, 2, 2>()) );
|
||||
CALL_SUBTEST_3( triangular(Matrix3d()) );
|
||||
CALL_SUBTEST_4( triangular(MatrixXcf(4, 4)) );
|
||||
CALL_SUBTEST_5( triangular(Matrix<std::complex<float>,8, 8>()) );
|
||||
CALL_SUBTEST_6( triangular(MatrixXcd(17,17)) );
|
||||
CALL_SUBTEST_7( triangular(Matrix<float,Dynamic,Dynamic,RowMajor>(5, 5)) );
|
||||
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);
|
||||
|
||||
CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) );
|
||||
CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) );
|
||||
CALL_SUBTEST_3( triangular_square(Matrix3d()) );
|
||||
CALL_SUBTEST_4( triangular_square(Matrix<std::complex<float>,8, 8>()) );
|
||||
CALL_SUBTEST_5( triangular_square(MatrixXcd(r,r)) );
|
||||
CALL_SUBTEST_6( triangular_square(Matrix<float,Dynamic,Dynamic,RowMajor>(r, r)) );
|
||||
|
||||
CALL_SUBTEST_7( triangular_rect(Matrix<float, 4, 5>()) );
|
||||
CALL_SUBTEST_8( triangular_rect(Matrix<double, 6, 2>()) );
|
||||
CALL_SUBTEST_9( triangular_rect(MatrixXcf(r, c)) );
|
||||
CALL_SUBTEST_5( triangular_rect(MatrixXcd(r, c)) );
|
||||
CALL_SUBTEST_6( triangular_rect(Matrix<float,Dynamic,Dynamic,RowMajor>(r, c)) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ void construct_at_boundary(int boundary)
|
||||
_buf += (16 - (_buf % 16)); // make 16-byte aligned
|
||||
_buf += boundary; // make exact boundary-aligned
|
||||
T *x = ::new(reinterpret_cast<void*>(_buf)) T;
|
||||
x[0].setZero(); // just in order to silence warnings
|
||||
x->~T();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -26,17 +26,18 @@
|
||||
#include <typeinfo>
|
||||
|
||||
template<typename Dst, typename Src>
|
||||
bool test_assign(const Dst&, const Src&, int vectorization, int unrolling)
|
||||
bool test_assign(const Dst&, const Src&, int traversal, int unrolling)
|
||||
{
|
||||
return ei_assign_traits<Dst,Src>::Vectorization==vectorization
|
||||
ei_assign_traits<Dst,Src>::debug();
|
||||
return ei_assign_traits<Dst,Src>::Traversal==traversal
|
||||
&& ei_assign_traits<Dst,Src>::Unrolling==unrolling;
|
||||
}
|
||||
|
||||
template<typename Xpr>
|
||||
bool test_redux(const Xpr&, int vectorization, int unrolling)
|
||||
bool test_redux(const Xpr&, int traversal, int unrolling)
|
||||
{
|
||||
typedef ei_redux_traits<ei_scalar_sum_op<typename Xpr::Scalar>,Xpr> traits;
|
||||
return traits::Vectorization==vectorization && traits::Unrolling==unrolling;
|
||||
return traits::Traversal==traversal && traits::Unrolling==unrolling;
|
||||
}
|
||||
|
||||
void test_vectorization_logic()
|
||||
@@ -45,61 +46,67 @@ void test_vectorization_logic()
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
|
||||
VERIFY(test_assign(Vector4f(),Vector4f(),
|
||||
InnerVectorization,CompleteUnrolling));
|
||||
InnerVectorizedTraversal,CompleteUnrolling));
|
||||
VERIFY(test_assign(Vector4f(),Vector4f()+Vector4f(),
|
||||
InnerVectorization,CompleteUnrolling));
|
||||
InnerVectorizedTraversal,CompleteUnrolling));
|
||||
VERIFY(test_assign(Vector4f(),Vector4f().cwiseProduct(Vector4f()),
|
||||
InnerVectorization,CompleteUnrolling));
|
||||
InnerVectorizedTraversal,CompleteUnrolling));
|
||||
VERIFY(test_assign(Vector4f(),Vector4f().cast<float>(),
|
||||
InnerVectorization,CompleteUnrolling));
|
||||
InnerVectorizedTraversal,CompleteUnrolling));
|
||||
|
||||
|
||||
VERIFY(test_assign(Matrix4f(),Matrix4f(),
|
||||
InnerVectorization,CompleteUnrolling));
|
||||
InnerVectorizedTraversal,CompleteUnrolling));
|
||||
VERIFY(test_assign(Matrix4f(),Matrix4f()+Matrix4f(),
|
||||
InnerVectorization,CompleteUnrolling));
|
||||
InnerVectorizedTraversal,CompleteUnrolling));
|
||||
VERIFY(test_assign(Matrix4f(),Matrix4f().cwiseProduct(Matrix4f()),
|
||||
InnerVectorization,CompleteUnrolling));
|
||||
InnerVectorizedTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_assign(Matrix<float,16,16>(),Matrix<float,16,16>()+Matrix<float,16,16>(),
|
||||
InnerVectorization,InnerUnrolling));
|
||||
InnerVectorizedTraversal,InnerUnrolling));
|
||||
|
||||
VERIFY(test_assign(Matrix<float,16,16,DontAlign>(),Matrix<float,16,16>()+Matrix<float,16,16>(),
|
||||
NoVectorization,InnerUnrolling));
|
||||
LinearTraversal,NoUnrolling));
|
||||
|
||||
VERIFY(test_assign(Matrix<float,2,2,DontAlign>(),Matrix<float,2,2>()+Matrix<float,2,2>(),
|
||||
LinearTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_assign(Matrix<float,6,2>(),Matrix<float,6,2>().cwiseQuotient(Matrix<float,6,2>()),
|
||||
LinearVectorization,CompleteUnrolling));
|
||||
LinearVectorizedTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_assign(Matrix<float,17,17>(),Matrix<float,17,17>()+Matrix<float,17,17>(),
|
||||
NoVectorization,InnerUnrolling));
|
||||
LinearTraversal,NoUnrolling));
|
||||
|
||||
VERIFY(test_assign(Matrix<float,3,3>(),Matrix<float,3,3>()+Matrix<float,3,3>(),
|
||||
LinearTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_assign(Matrix<float,4,4>(),Matrix<float,17,17>().block<4,4>(2,3)+Matrix<float,17,17>().block<4,4>(10,4),
|
||||
NoVectorization,CompleteUnrolling));
|
||||
DefaultTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_assign(MatrixXf(10,10),MatrixXf(20,20).block(10,10,2,3),
|
||||
SliceVectorization,NoUnrolling));
|
||||
SliceVectorizedTraversal,NoUnrolling));
|
||||
|
||||
|
||||
VERIFY(test_redux(VectorXf(10),
|
||||
LinearVectorization,NoUnrolling));
|
||||
LinearVectorizedTraversal,NoUnrolling));
|
||||
|
||||
VERIFY(test_redux(Matrix<float,5,2>(),
|
||||
NoVectorization,CompleteUnrolling));
|
||||
DefaultTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_redux(Matrix<float,6,2>(),
|
||||
LinearVectorization,CompleteUnrolling));
|
||||
LinearVectorizedTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_redux(Matrix<float,16,16>(),
|
||||
LinearVectorization,NoUnrolling));
|
||||
LinearVectorizedTraversal,NoUnrolling));
|
||||
|
||||
VERIFY(test_redux(Matrix<float,16,16>().block<4,4>(1,2),
|
||||
NoVectorization,CompleteUnrolling));
|
||||
DefaultTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_redux(Matrix<float,16,16>().block<8,1>(1,2),
|
||||
LinearVectorization,CompleteUnrolling));
|
||||
LinearVectorizedTraversal,CompleteUnrolling));
|
||||
|
||||
VERIFY(test_redux(Matrix<double,7,3>(),
|
||||
NoVectorization,CompleteUnrolling));
|
||||
DefaultTraversal,CompleteUnrolling));
|
||||
|
||||
#endif // EIGEN_VECTORIZE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user