Compare commits

...

26 Commits

Author SHA1 Message Date
Benoit Jacob
8f1ce52e76 bump 2009-11-25 08:46:42 -05:00
Benoit Jacob
268df314f1 make the inverse_4x4 test pass more consistently 2009-11-25 08:43:20 -05:00
Benoit Jacob
522022ebfc wow, restore Gael's changeset 5455d6fbe8
that I had accidentally undone in my changeset c64ca6870e
.
2009-11-25 08:31:25 -05:00
Thomas Capricelli
d048d7e712 fix bitbucket url after recent change 2009-11-24 23:08:16 +01:00
Benoit Jacob
cd3c8a9404 typo 2009-11-23 11:23:30 -05:00
Benoit Jacob
ec8f37ac75 improve precision test 2009-11-23 11:20:48 -05:00
Benoit Jacob
fc7f39980c backport improvement in 4x4 inverse precisio, and rigorous precision test 2009-11-23 10:27:10 -05:00
Gael Guennebaud
70af59c455 an attempt to fix compilation with recent MSVC 2009-11-23 10:29:40 +01:00
Benoit Jacob
f4dd399499 fix warnings 2009-11-16 14:15:47 -05:00
Benoit Jacob
153557527e backport: init-by-zero option: resize with same size must be a NOP 2009-11-16 13:47:02 -05:00
Benoit Jacob
6aad7f80ff avoid infinite loop, optimization not important, so a plain for loop is the safe way 2009-11-12 14:09:53 -05:00
Benoit Jacob
e3f6c3115a backport the initialize-by-0 option 2009-11-12 12:53:24 -05:00
Benoit Jacob
a2c838ff8f fix PowerPC platform detection 2009-11-11 10:52:00 -05:00
Thomas Capricelli
1e2f56c35a backport of b53c2fcc99
: fix install dir for *.pc

Ingmar Vanhassel <ingmar@exherbo.org>:
Packages that don't install architecture-specific files should install
their pkg-config file to datadir, not libdir.
2009-11-11 15:35:12 +01:00
Hauke Heibel
808c4e9581 Fixed the packport of 62 - Packet4f/d/i does not exist in 2.0. 2009-11-05 10:49:49 +01:00
Hauke Heibel
65331c3884 backporting3979f6d8aad001174160774b49b747430a7686b5
: fixed bug #62
2009-11-04 17:49:34 +01:00
Benoit Jacob
e158cdd61d fix Matrix::Map/MapAligned documentation, and rephrase the tutorial on Map 2009-10-31 14:45:50 -04:00
Benoit Jacob
c64ca6870e this explicit keyword can't hurt 2009-10-31 11:49:20 -04:00
Benoit Jacob
6a90f6c5f0 * default MatrixBase ctor: make it protected, make it a static assert, only do the check when debugging eigen to avoid slowing down compilation for everybody (this check is paranoiac, it's very seldom useful)
* add private MatrixBase ctors to catch cases when the user tries to construct MatrixBase objects directly
2009-10-31 11:48:33 -04:00
Gael Guennebaud
22dd13fdb9 backporting fix of #65 2009-10-29 14:26:38 +01:00
Gael Guennebaud
5455d6fbe8 backporting fix of #65 2009-10-29 14:26:00 +01:00
Benoit Jacob
de693cf34a remove extra ; 2009-10-28 10:04:13 -04:00
Benoit Jacob
21c4e0802d fix potential warning 2009-10-28 09:45:09 -04:00
Benoit Jacob
241b9d34a7 Hey, I was insomniac too ;)
This restores much of the performance benefit of Euler's method, without compromising accuracy (tested on 1e+7 matrices). Namely, my benchmark now runs in 1.5 s instead of 2.2 s. The same in the default branch runs in 1.08 s instead of 1.9 s, so the default branch benefits even more!
2009-10-28 03:50:29 -04:00
Benoit Jacob
9e15a6da2e Fix 4x4 matrix inversion. Applying Euler's trick is more tricky than what "high performance matrix inversion" websites would have you believe. Our 4x4 matrix inversion wasn't numerically stable, because in applying the Euler trick we didn't take the 2x2 block of biggest determinant. As a result, with float, we got relative errors above 1% every 1000 random matrices, and we got completely wrong results every 10000 matrices.
Note that this decreases the performance, but we're still significantly faster than the brutal cofactors approach.
2009-10-27 07:35:25 -04:00
Benoit Jacob
3d365a75cd Added tag 2.0.9 for changeset 38bc82a6f7 2009-10-24 19:38:58 -04:00
13 changed files with 231 additions and 70 deletions

View File

@@ -7,7 +7,7 @@ set(INCLUDE_INSTALL_DIR
"The directory where we install the header files"
FORCE)
set(EIGEN_VERSION_NUMBER "2.0.9")
set(EIGEN_VERSION_NUMBER "2.0.10")
set(EIGEN_VERSION "${EIGEN_VERSION_NUMBER}")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
@@ -88,7 +88,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
if(EIGEN_BUILD_PKGCONFIG)
configure_file(eigen2.pc.in eigen2.pc) # uses INCLUDE_INSTALL_DIR
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/eigen2.pc
DESTINATION lib/pkgconfig
DESTINATION share/pkgconfig
)
endif(EIGEN_BUILD_PKGCONFIG)

View File

@@ -222,7 +222,7 @@ class Block<MatrixType,BlockRows,BlockCols,PacketAccess,HasDirectAccess>
class InnerIterator;
typedef typename ei_traits<Block>::AlignedDerivedType AlignedDerivedType;
friend class Block<MatrixType,BlockRows,BlockCols,PacketAccess==AsRequested?ForceAligned:AsRequested,HasDirectAccess>;
friend class Block<MatrixType,BlockRows,BlockCols,PacketAccess==int(AsRequested)?ForceAligned:AsRequested,HasDirectAccess>;
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)

View File

@@ -25,6 +25,11 @@
#ifndef EIGEN_MATRIX_H
#define EIGEN_MATRIX_H
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED for(int i=0;i<base().size();++i) coeffRef(i)=Scalar(0);
#else
# define EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
#endif
/** \class Matrix
*
@@ -233,7 +238,14 @@ class Matrix
&& (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
&& (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols)
&& (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols));
m_storage.resize(rows * cols, rows, cols);
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
int size = rows*cols;
bool size_changed = size != this->size();
m_storage.resize(size, rows, cols);
if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
#else
m_storage.resize(rows*cols, rows, cols);
#endif
}
/** Resizes \c *this to a vector of length \a size
@@ -243,10 +255,17 @@ class Matrix
inline void resize(int size)
{
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == size);
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
bool size_changed = size != this->size();
#endif
if(RowsAtCompileTime == 1)
m_storage.resize(size, 1, size);
else
m_storage.resize(size, size, 1);
#ifdef EIGEN_INITIALIZE_MATRICES_BY_ZERO
if(size_changed) EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
#endif
}
/** Copies the value of the expression \a other into \c *this with automatic resizing.
@@ -290,13 +309,14 @@ class Matrix
EIGEN_STRONG_INLINE explicit Matrix() : m_storage()
{
_check_template_params();
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** \internal */
Matrix(ei_constructor_without_unaligned_array_assert)
: m_storage(ei_constructor_without_unaligned_array_assert())
{}
{EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED}
#endif
/** Constructs a vector or row-vector with given dimension. \only_for_vectors
@@ -312,6 +332,7 @@ class Matrix
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix)
ei_assert(dim > 0);
ei_assert(SizeAtCompileTime == Dynamic || SizeAtCompileTime == dim);
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
}
/** This constructor has two very different behaviors, depending on the type of *this.
@@ -337,6 +358,7 @@ class Matrix
{
ei_assert(x > 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == x)
&& y > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == y));
EIGEN_INITIALIZE_BY_ZERO_IF_THAT_OPTION_IS_ENABLED
}
}
/** constructs an initialized 2D vector with given coefficients */
@@ -402,9 +424,10 @@ class Matrix
void swap(const MatrixBase<OtherDerived>& other);
/** \name Map
* These are convenience functions returning Map objects. The Map() static functions return unaligned Map objects,
* while the AlignedMap() functions return aligned Map objects and thus should be called only with 16-byte-aligned
* \a data pointers.
* These are convenience functions returning Map objects.
*
* \warning Do not use MapAligned in the Eigen 2.0. Mapping aligned arrays will be fully
* supported in Eigen 3.0 (already implemented in the development branch)
*
* \see class Map
*/

View File

@@ -136,12 +136,6 @@ template<typename Derived> class MatrixBase
*/
};
/** Default constructor. Just checks at compile-time for self-consistency of the flags. */
MatrixBase()
{
ei_assert(ei_are_flags_consistent<Flags>::ret);
}
#ifndef EIGEN_PARSED_BY_DOXYGEN
/** This is the "real scalar" type; if the \a Scalar type is already real numbers
* (e.g. int, float or double) then \a RealScalar is just the same as \a Scalar. If
@@ -165,7 +159,7 @@ template<typename Derived> class MatrixBase
inline int size() const { return rows() * cols(); }
/** \returns the number of nonzero coefficients which is in practice the number
* of stored coefficients. */
inline int nonZeros() const { return derived.nonZeros(); }
inline int nonZeros() const { return size(); }
/** \returns true if either the number of rows or the number of columns is equal to 1.
* In other words, this function returns
* \code rows()==1 || cols()==1 \endcode
@@ -627,6 +621,24 @@ template<typename Derived> class MatrixBase
#ifdef EIGEN_MATRIXBASE_PLUGIN
#include EIGEN_MATRIXBASE_PLUGIN
#endif
protected:
/** Default constructor. Do nothing. */
MatrixBase()
{
/* Just checks for self-consistency of the flags.
* Only do it when debugging Eigen, as this borders on paranoiac and could slow compilation down
*/
#ifdef EIGEN_INTERNAL_DEBUGGING
EIGEN_STATIC_ASSERT(ei_are_flags_consistent<Flags>::ret,
INVALID_MATRIXBASE_TEMPLATE_PARAMETERS)
#endif
}
private:
explicit MatrixBase(int);
MatrixBase(int,int);
template<typename OtherDerived> explicit MatrixBase(const MatrixBase<OtherDerived>&);
};
#endif // EIGEN_MATRIXBASE_H

View File

@@ -69,7 +69,6 @@ template<typename MatrixType> class Transpose
inline int rows() const { return m_matrix.cols(); }
inline int cols() const { return m_matrix.rows(); }
inline int nonZeros() const { return m_matrix.nonZeros(); }
inline int stride(void) const { return m_matrix.stride(); }
inline Scalar& coeffRef(int row, int col)

View File

@@ -114,9 +114,15 @@ template<> EIGEN_STRONG_INLINE void ei_pstoreu<float>(float* to, const __m128&
template<> EIGEN_STRONG_INLINE void ei_pstoreu<double>(double* to, const __m128d& from) { _mm_storeu_pd(to, from); }
template<> EIGEN_STRONG_INLINE void ei_pstoreu<int>(int* to, const __m128i& from) { _mm_storeu_si128(reinterpret_cast<__m128i*>(to), from); }
#ifdef _MSC_VER
// this fix internal compilation error
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { float x = _mm_cvtss_f32(a); return x; }
#if defined(_MSC_VER) && (_MSC_VER <= 1500) && defined(_WIN64)
// The temporary variable fixes an internal compilation error.
// Direct of the struct members fixed bug #62.
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { return a.m128_f32[0]; }
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { return a.m128d_f64[0]; }
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { int x = _mm_cvtsi128_si32(a); return x; }
#elif defined(_MSC_VER) && (_MSC_VER <= 1500)
// The temporary variable fixes an internal compilation error.
template<> EIGEN_STRONG_INLINE float ei_pfirst<__m128>(const __m128& a) { float x = _mm_cvtss_f32(a); return x; }
template<> EIGEN_STRONG_INLINE double ei_pfirst<__m128d>(const __m128d& a) { double x = _mm_cvtsd_f64(a); return x; }
template<> EIGEN_STRONG_INLINE int ei_pfirst<__m128i>(const __m128i& a) { int x = _mm_cvtsi128_si32(a); return x; }
#else

View File

@@ -30,7 +30,7 @@
#define EIGEN_WORLD_VERSION 2
#define EIGEN_MAJOR_VERSION 0
#define EIGEN_MINOR_VERSION 9
#define EIGEN_MINOR_VERSION 10
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
@@ -39,7 +39,7 @@
// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable 16 byte alignment on all
// platforms where vectorization might be enabled. In theory we could always enable alignment, but it can be a cause of problems
// on some platforms, so we just disable it in certain common platform (compiler+architecture combinations) to avoid these problems.
#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ia64__))
#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ppc__) || defined(__ia64__))
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 1
#else
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 0

View File

@@ -74,6 +74,7 @@
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES,
THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES,
INVALID_MATRIX_TEMPLATE_PARAMETERS,
INVALID_MATRIXBASE_TEMPLATE_PARAMETERS,
BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER,
THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX
};

View File

@@ -119,46 +119,54 @@ bool ei_compute_inverse_in_size4_case_helper(const MatrixType& matrix, MatrixTyp
}
template<typename MatrixType>
void ei_compute_inverse_in_size4_case(const MatrixType& matrix, MatrixType* result)
void ei_compute_inverse_in_size4_case(const MatrixType& _matrix, MatrixType* result)
{
if(ei_compute_inverse_in_size4_case_helper(matrix, result))
{
// good ! The topleft 2x2 block was invertible, so the 2x2 blocks approach is successful.
return;
}
else
{
// rare case: the topleft 2x2 block is not invertible (but the matrix itself is assumed to be).
// since this is a rare case, we don't need to optimize it. We just want to handle it with little
// additional code.
MatrixType m(matrix);
m.row(0).swap(m.row(2));
m.row(1).swap(m.row(3));
if(ei_compute_inverse_in_size4_case_helper(m, result))
{
// good, the topleft 2x2 block of m is invertible. Since m is different from matrix in that some
// rows were permuted, the actual inverse of matrix is derived from the inverse of m by permuting
// the corresponding columns.
result->col(0).swap(result->col(2));
result->col(1).swap(result->col(3));
}
else
{
// last possible case. Since matrix is assumed to be invertible, this last case has to work.
// first, undo the swaps previously made
m.row(0).swap(m.row(2));
m.row(1).swap(m.row(3));
// swap row 0 with the the row among 0 and 1 that has the biggest 2 first coeffs
int swap0with = ei_abs(m.coeff(0,0))+ei_abs(m.coeff(0,1))>ei_abs(m.coeff(1,0))+ei_abs(m.coeff(1,1)) ? 0 : 1;
m.row(0).swap(m.row(swap0with));
// swap row 1 with the the row among 2 and 3 that has the biggest 2 first coeffs
int swap1with = ei_abs(m.coeff(2,0))+ei_abs(m.coeff(2,1))>ei_abs(m.coeff(3,0))+ei_abs(m.coeff(3,1)) ? 2 : 3;
m.row(1).swap(m.row(swap1with));
ei_compute_inverse_in_size4_case_helper(m, result);
result->col(1).swap(result->col(swap1with));
result->col(0).swap(result->col(swap0with));
}
}
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
// we will do row permutations on the matrix. This copy should have negligible cost.
// if not, consider working in-place on the matrix (const-cast it, but then undo the permutations
// to nevertheless honor constness)
typename MatrixType::PlainMatrixType matrix(_matrix);
// let's extract from the 2 first colums a 2x2 block whose determinant is as big as possible.
int good_row0, good_row1, good_i;
Matrix<RealScalar,6,1> absdet;
// any 2x2 block with determinant above this threshold will be considered good enough.
// The magic value 1e-1 here comes from experimentation. The bigger it is, the higher the precision,
// the slower the computation. This value 1e-1 gives precision almost as good as the brutal cofactors
// algorithm, both in average and in worst-case precision.
RealScalar d = (matrix.col(0).squaredNorm()+matrix.col(1).squaredNorm()) * RealScalar(1e-1);
#define ei_inv_size4_helper_macro(i,row0,row1) \
absdet[i] = ei_abs(matrix.coeff(row0,0)*matrix.coeff(row1,1) \
- matrix.coeff(row0,1)*matrix.coeff(row1,0)); \
if(absdet[i] > d) { good_row0=row0; good_row1=row1; goto good; }
ei_inv_size4_helper_macro(0,0,1)
ei_inv_size4_helper_macro(1,0,2)
ei_inv_size4_helper_macro(2,0,3)
ei_inv_size4_helper_macro(3,1,2)
ei_inv_size4_helper_macro(4,1,3)
ei_inv_size4_helper_macro(5,2,3)
// no 2x2 block has determinant bigger than the threshold. So just take the one that
// has the biggest determinant
absdet.maxCoeff(&good_i);
good_row0 = good_i <= 2 ? 0 : good_i <= 4 ? 1 : 2;
good_row1 = good_i <= 2 ? good_i+1 : good_i <= 4 ? good_i-1 : 3;
// now good_row0 and good_row1 are correctly set
good:
// do row permutations to move this 2x2 block to the top
matrix.row(0).swap(matrix.row(good_row0));
matrix.row(1).swap(matrix.row(good_row1));
// now applying our helper function is numerically stable
ei_compute_inverse_in_size4_case_helper(matrix, result);
// Since we did row permutations on the original matrix, we need to do column permutations
// in the reverse order on the inverse
result->col(1).swap(result->col(good_row1));
result->col(0).swap(result->col(good_row0));
}
/***********************************************

View File

@@ -229,17 +229,24 @@ Of course, fixed-size matrices can't be resized.
\subsection TutorialMap Map
Any memory buffer can be mapped as an Eigen expression:
<table class="tutorial_code"><tr><td>
Any memory buffer can be mapped as an Eigen expression using the Map() static method:
\code
std::vector<float> stlarray(10);
Map<VectorXf>(&stlarray[0], stlarray.size()).setOnes();
int data[4] = 1, 2, 3, 4;
Matrix2i mat2x2(data);
MatrixXi mat2x2 = Map<Matrix2i>(data);
MatrixXi mat2x2 = Map<MatrixXi>(data,2,2);
VectorXf::Map(&stlarray[0], stlarray.size()).squaredNorm();
\endcode
Here VectorXf::Map returns an object of class Map<VectorXf>, which behaves like a VectorXf except that it uses the existing array. You can write to this object, that will write to the existing array. You can also construct a named obtect to reuse it:
\code
float array[rows*cols];
Map<MatrixXf> m(array,rows,cols);
m = othermatrix1 * othermatrix2;
m.eigenvalues();
\endcode
In the fixed-size case, no need to pass sizes:
\code
float array[9];
Map<Matrix3d> m(array);
Matrix3d::Map(array).setIdentity();
\endcode
</td></tr></table>

View File

@@ -222,6 +222,8 @@ ei_add_test(sparse_product)
ei_add_test(swap)
ei_add_test(visitor)
ei_add_test(prec_inverse_4x4 ${EI_OFLAG})
# print a summary of the different options
message("************************************************************")
message("*** Eigen's unit tests configuration summary ***")

103
test/prec_inverse_4x4.cpp Normal file
View File

@@ -0,0 +1,103 @@
// 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 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>"; }
#define EIGEN_DEBUG_VAR(x) std::cerr << #x << " = " << x << std::endl;
template<typename T> inline typename NumTraits<T>::Real epsilon()
{
return std::numeric_limits<typename NumTraits<T>::Real>::epsilon();
}
template<typename MatrixType> void inverse_permutation_4x4()
{
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
double error_max = 0.;
Vector4i indices(0,1,2,3);
for(int i = 0; i < 24; ++i)
{
MatrixType m = MatrixType::Zero();
m(indices(0),0) = 1;
m(indices(1),1) = 1;
m(indices(2),2) = 1;
m(indices(3),3) = 1;
MatrixType inv = m.inverse();
double error = double( (m*inv-MatrixType::Identity()).norm() / epsilon<Scalar>() );
error_max = std::max(error_max, error);
std::next_permutation(indices.data(),indices.data()+4);
}
std::cerr << "inverse_permutation_4x4, Scalar = " << type_name<Scalar>() << std::endl;
EIGEN_DEBUG_VAR(error_max);
VERIFY(error_max < 1. );
}
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 < 10 * 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.4 : 1.4) );
VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 160.0 : 75.) );
}
void test_prec_inverse_4x4()
{
CALL_SUBTEST((inverse_permutation_4x4<Matrix4f>()));
CALL_SUBTEST(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
CALL_SUBTEST((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
CALL_SUBTEST(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
CALL_SUBTEST((inverse_permutation_4x4<Matrix4cf>()));
CALL_SUBTEST((inverse_general_4x4<Matrix4cf>(50000 * g_repeat)));
}

View File

@@ -39,7 +39,7 @@
# VERSION=opensuse-11.1
# WORK_DIR=/home/gael/Coding/eigen2/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
@@ -133,7 +133,7 @@ endif(NOT EIGEN_MODE)
## mandatory variables (the default should be ok in most cases):
SET (CTEST_CVS_COMMAND "hg")
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone -r 2.0 http://bitbucket.org/eigen/eigen2 \"${CTEST_SOURCE_DIRECTORY}\"")
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone -r 2.0 http://bitbucket.org/eigen/eigen \"${CTEST_SOURCE_DIRECTORY}\"")
# which ctest command to use for running the dashboard
SET (CTEST_COMMAND "${EIGEN_CMAKE_DIR}ctest -D ${EIGEN_MODE}")