mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4f9515ca0 | ||
|
|
0361e8a7aa | ||
|
|
b7035b67b7 | ||
|
|
a1eae7ad00 | ||
|
|
30b605bef8 | ||
|
|
990615e884 | ||
|
|
841ec959e5 | ||
|
|
2dce3311f7 | ||
|
|
8eab0bccbf | ||
|
|
f5a167b3e7 | ||
|
|
f845d15192 | ||
|
|
7ae2bc6109 | ||
|
|
654fea39dc | ||
|
|
fa44566305 | ||
|
|
8302ce6cdc | ||
|
|
c6eb9ef60e | ||
|
|
9bff5e4f67 | ||
|
|
5f350c51b3 | ||
|
|
df0b107243 |
@@ -1,5 +1,5 @@
|
||||
project(Eigen)
|
||||
set(EIGEN_VERSION_NUMBER "2.0.3")
|
||||
set(EIGEN_VERSION_NUMBER "2.0.4")
|
||||
|
||||
#if the svnversion program is absent, this will leave the SVN_REVISION string empty,
|
||||
#but won't stop CMake.
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
## project to incorporate the testing dashboard.
|
||||
## # The following are required to uses Dart and the Cdash dashboard
|
||||
## ENABLE_TESTING()
|
||||
## INCLUDE(Dart)
|
||||
set(CTEST_PROJECT_NAME "Eigen")
|
||||
set(CTEST_NIGHTLY_START_TIME "05:00:00 UTC")
|
||||
## INCLUDE(CTest)
|
||||
set(CTEST_PROJECT_NAME "Eigen 2.0")
|
||||
set(CTEST_NIGHTLY_START_TIME "06:00:00 UTC")
|
||||
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "www.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/CDashPublic/submit.php?project=Eigen")
|
||||
set(CTEST_DROP_SITE "eigen.tuxfamily.org")
|
||||
set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Eigen+2.0")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
|
||||
@@ -180,7 +180,7 @@ static void ei_cache_friendly_product(
|
||||
{
|
||||
int offsetblock = l2k * (l2blockRowEnd-l2i) + (l1i-l2i)*(l2blockSizeEnd-l2k) - l2k*MaxBlockRows;
|
||||
const Scalar* EIGEN_RESTRICT localB = &block[offsetblock];
|
||||
|
||||
|
||||
for(int l1j=l2j; l1j<l2blockColEnd; l1j+=1)
|
||||
{
|
||||
const Scalar* EIGEN_RESTRICT rhsColumn;
|
||||
|
||||
@@ -61,12 +61,8 @@ inline int ei_exp(int) { ei_assert(false); return 0; }
|
||||
inline int ei_log(int) { ei_assert(false); return 0; }
|
||||
inline int ei_sin(int) { ei_assert(false); return 0; }
|
||||
inline int ei_cos(int) { ei_assert(false); return 0; }
|
||||
|
||||
#if EIGEN_GNUC_AT_LEAST(4,3)
|
||||
inline int ei_pow(int x, int y) { return int(std::pow(x, y)); }
|
||||
#else
|
||||
inline int ei_atan2(int, int) { ei_assert(false); return 0; }
|
||||
inline int ei_pow(int x, int y) { return int(std::pow(double(x), y)); }
|
||||
#endif
|
||||
|
||||
template<> inline int ei_random(int a, int b)
|
||||
{
|
||||
@@ -106,6 +102,7 @@ inline float ei_exp(float x) { return std::exp(x); }
|
||||
inline float ei_log(float x) { return std::log(x); }
|
||||
inline float ei_sin(float x) { return std::sin(x); }
|
||||
inline float ei_cos(float x) { return std::cos(x); }
|
||||
inline float ei_atan2(float y, float x) { return std::atan2(y,x); }
|
||||
inline float ei_pow(float x, float y) { return std::pow(x, y); }
|
||||
|
||||
template<> inline float ei_random(float a, float b)
|
||||
@@ -153,6 +150,7 @@ inline double ei_exp(double x) { return std::exp(x); }
|
||||
inline double ei_log(double x) { return std::log(x); }
|
||||
inline double ei_sin(double x) { return std::sin(x); }
|
||||
inline double ei_cos(double x) { return std::cos(x); }
|
||||
inline double ei_atan2(double y, double x) { return std::atan2(y,x); }
|
||||
inline double ei_pow(double x, double y) { return std::pow(x, y); }
|
||||
|
||||
template<> inline double ei_random(double a, double b)
|
||||
@@ -197,6 +195,7 @@ inline float ei_abs2(const std::complex<float>& x) { return std::norm(x); }
|
||||
inline std::complex<float> ei_exp(std::complex<float> x) { return std::exp(x); }
|
||||
inline std::complex<float> ei_sin(std::complex<float> x) { return std::sin(x); }
|
||||
inline std::complex<float> ei_cos(std::complex<float> x) { return std::cos(x); }
|
||||
inline std::complex<float> ei_atan2(std::complex<float>, std::complex<float> ) { ei_assert(false); return 0; }
|
||||
|
||||
template<> inline std::complex<float> ei_random()
|
||||
{
|
||||
@@ -231,6 +230,7 @@ inline double ei_abs2(const std::complex<double>& x) { return std::norm(x); }
|
||||
inline std::complex<double> ei_exp(std::complex<double> x) { return std::exp(x); }
|
||||
inline std::complex<double> ei_sin(std::complex<double> x) { return std::sin(x); }
|
||||
inline std::complex<double> ei_cos(std::complex<double> x) { return std::cos(x); }
|
||||
inline std::complex<double> ei_atan2(std::complex<double>, std::complex<double>) { ei_assert(false); return 0; }
|
||||
|
||||
template<> inline std::complex<double> ei_random()
|
||||
{
|
||||
@@ -268,6 +268,7 @@ inline long double ei_exp(long double x) { return std::exp(x); }
|
||||
inline long double ei_log(long double x) { return std::log(x); }
|
||||
inline long double ei_sin(long double x) { return std::sin(x); }
|
||||
inline long double ei_cos(long double x) { return std::cos(x); }
|
||||
inline long double ei_atan2(long double y, long double x) { return std::atan2(y,x); }
|
||||
inline long double ei_pow(long double x, long double y) { return std::pow(x, y); }
|
||||
|
||||
template<> inline long double ei_random(long double a, long double b)
|
||||
|
||||
@@ -507,10 +507,16 @@ class Matrix
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE Matrix& _set(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
_resize_to_match(other);
|
||||
return Base::operator=(other);
|
||||
_set_selector(other.derived(), typename ei_meta_if<(int(OtherDerived::Flags) & EvalBeforeAssigningBit), ei_meta_true, ei_meta_false>::ret());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const ei_meta_true&) { _set_noalias(other.eval()); }
|
||||
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const ei_meta_false&) { _set_noalias(other); }
|
||||
|
||||
/** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which
|
||||
* is the case when creating a new matrix) so one can enforce lazy evaluation.
|
||||
*
|
||||
|
||||
@@ -299,7 +299,7 @@ template<typename OtherDerived>
|
||||
inline Derived &
|
||||
MatrixBase<Derived>::operator*=(const MatrixBase<OtherDerived> &other)
|
||||
{
|
||||
return *this = *this * other;
|
||||
return derived() = derived() * other.derived();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#define EIGEN_WORLD_VERSION 2
|
||||
#define EIGEN_MAJOR_VERSION 0
|
||||
#define EIGEN_MINOR_VERSION 3
|
||||
#define EIGEN_MINOR_VERSION 4
|
||||
|
||||
#define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \
|
||||
(EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \
|
||||
|
||||
@@ -238,16 +238,39 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
|
||||
|
||||
|
||||
#if EIGEN_ARCH_WANTS_ALIGNMENT
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
||||
void* operator new(size_t size, const std::nothrow_t&) throw() { \
|
||||
try { return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); } \
|
||||
catch (...) { return 0; } \
|
||||
return 0; \
|
||||
}
|
||||
#else
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
||||
void* operator new(size_t size, const std::nothrow_t&) throw() { \
|
||||
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
|
||||
void *operator new(size_t size) throw() { \
|
||||
void *operator new(size_t size) { \
|
||||
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
} \
|
||||
void *operator new[](size_t size) throw() { \
|
||||
void *operator new[](size_t size) { \
|
||||
return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
|
||||
} \
|
||||
void operator delete(void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
void operator delete[](void * ptr) { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
void *operator new(size_t, void *ptr) throw() { return ptr; } \
|
||||
void operator delete(void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
void operator delete[](void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
|
||||
/* in-place new and delete. since (at least afaik) there is no actual */ \
|
||||
/* memory allocated we can safely let the default implementation handle */ \
|
||||
/* this particular case. */ \
|
||||
static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
|
||||
void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
|
||||
/* nothrow-new (returns zero instead of std::bad_alloc) */ \
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
||||
void operator delete(void *ptr, const std::nothrow_t&) throw() { \
|
||||
Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); \
|
||||
} \
|
||||
typedef void ei_operator_new_marker_type;
|
||||
#else
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
|
||||
|
||||
@@ -60,31 +60,31 @@ MatrixBase<Derived>::eulerAngles(int a0, int a1, int a2) const
|
||||
if (a0==a2)
|
||||
{
|
||||
Scalar s = Vector2(coeff(j,i) , coeff(k,i)).norm();
|
||||
res[1] = std::atan2(s, coeff(i,i));
|
||||
res[1] = ei_atan2(s, coeff(i,i));
|
||||
if (s > epsilon)
|
||||
{
|
||||
res[0] = std::atan2(coeff(j,i), coeff(k,i));
|
||||
res[2] = std::atan2(coeff(i,j),-coeff(i,k));
|
||||
res[0] = ei_atan2(coeff(j,i), coeff(k,i));
|
||||
res[2] = ei_atan2(coeff(i,j),-coeff(i,k));
|
||||
}
|
||||
else
|
||||
{
|
||||
res[0] = Scalar(0);
|
||||
res[2] = (coeff(i,i)>0?1:-1)*std::atan2(-coeff(k,j), coeff(j,j));
|
||||
res[2] = (coeff(i,i)>0?1:-1)*ei_atan2(-coeff(k,j), coeff(j,j));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Scalar c = Vector2(coeff(i,i) , coeff(i,j)).norm();
|
||||
res[1] = std::atan2(-coeff(i,k), c);
|
||||
res[1] = ei_atan2(-coeff(i,k), c);
|
||||
if (c > epsilon)
|
||||
{
|
||||
res[0] = std::atan2(coeff(j,k), coeff(k,k));
|
||||
res[2] = std::atan2(coeff(i,j), coeff(i,i));
|
||||
res[0] = ei_atan2(coeff(j,k), coeff(k,k));
|
||||
res[2] = ei_atan2(coeff(i,j), coeff(i,i));
|
||||
}
|
||||
else
|
||||
{
|
||||
res[0] = Scalar(0);
|
||||
res[2] = (coeff(i,k)>0?1:-1)*std::atan2(-coeff(k,j), coeff(j,j));
|
||||
res[2] = (coeff(i,k)>0?1:-1)*ei_atan2(-coeff(k,j), coeff(j,j));
|
||||
}
|
||||
}
|
||||
if (!odd)
|
||||
|
||||
@@ -346,7 +346,6 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
|
||||
{
|
||||
Vector3 v0 = a.normalized();
|
||||
Vector3 v1 = b.normalized();
|
||||
Vector3 axis = v0.cross(v1);
|
||||
Scalar c = v0.dot(v1);
|
||||
|
||||
// if dot == 1, vectors are the same
|
||||
@@ -354,7 +353,17 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
|
||||
{
|
||||
// set to identity
|
||||
this->w() = 1; this->vec().setZero();
|
||||
return *this;
|
||||
}
|
||||
// if dot == -1, vectors are opposites
|
||||
if (ei_isApprox(c,Scalar(-1)))
|
||||
{
|
||||
this->vec() = v0.unitOrthogonal();
|
||||
this->w() = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector3 axis = v0.cross(v1);
|
||||
Scalar s = ei_sqrt((Scalar(1)+c)*Scalar(2));
|
||||
Scalar invs = Scalar(1)/s;
|
||||
this->vec() = axis * invs;
|
||||
|
||||
@@ -335,9 +335,9 @@ template<typename Scalar, int Dim>
|
||||
QMatrix Transform<Scalar,Dim>::toQMatrix(void) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return QMatrix(other.coeffRef(0,0), other.coeffRef(1,0),
|
||||
other.coeffRef(0,1), other.coeffRef(1,1),
|
||||
other.coeffRef(0,2), other.coeffRef(1,2));
|
||||
return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
|
||||
m_matrix.coeff(0,1), m_matrix.coeff(1,1),
|
||||
m_matrix.coeff(0,2), m_matrix.coeff(1,2));
|
||||
}
|
||||
|
||||
/** Initialises \c *this from a QTransform assuming the dimension is 2.
|
||||
@@ -369,12 +369,12 @@ Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
|
||||
* This function is available only if the token EIGEN_QT_SUPPORT is defined.
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
QMatrix Transform<Scalar,Dim>::toQTransform(void) const
|
||||
QTransform Transform<Scalar,Dim>::toQTransform(void) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return QTransform(other.coeffRef(0,0), other.coeffRef(1,0), other.coeffRef(2,0)
|
||||
other.coeffRef(0,1), other.coeffRef(1,1), other.coeffRef(2,1)
|
||||
other.coeffRef(0,2), other.coeffRef(1,2), other.coeffRef(2,2);
|
||||
return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
|
||||
m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
|
||||
m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,9 +16,12 @@ void foo()
|
||||
|
||||
GCC assumes that the stack is already 16-byte-aligned so that the object \a q will be created at a 16-byte-aligned location. For this reason, it doesn't take any special care to explicitly align the object \a q, as Eigen requires.
|
||||
|
||||
The problem is that this assumption is wrong on Windows, where the stack is not guaranteed to have 16-byte alignment. This results in the object 'q' being created at an unaligned location, making your program crash with the \ref UnalignedArrayAssert "assertion on unaligned arrays".
|
||||
The problem is that, in some particular cases, this assumption can be wrong on Windows, where the stack is only guaranteed to have 4-byte alignment. Indeed, even though GCC takes care of aligning the stack in the main function and does its best to keep it aligned, when a function is called from another thread or from a binary compiled with another compiler, the stack alignment can be corrupted. This results in the object 'q' being created at an unaligned location, making your program crash with the \ref UnalignedArrayAssert "assertion on unaligned arrays". So far we found the three following solutions.
|
||||
|
||||
A local solution is to mark your function with this attribute:
|
||||
|
||||
\section sec_sol1 Local solution
|
||||
|
||||
A local solution is to mark such a function with this attribute:
|
||||
\code
|
||||
__attribute__((force_align_arg_pointer)) void foo()
|
||||
{
|
||||
@@ -26,17 +29,24 @@ __attribute__((force_align_arg_pointer)) void foo()
|
||||
//...
|
||||
}
|
||||
\endcode
|
||||
Read <a href="http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Function-Attributes.html#Function-Attributes">this GCC documentation</a> to understand what this does. Of course this should only be done on GCC on Windows, so for portability you'll have to encapsulate this in a macro which you leave empty on other platforms. Also this needs to be done for every such function, which is inconvenient! So you may prefer the following global solution:
|
||||
Read <a href="http://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Function-Attributes.html#Function-Attributes">this GCC documentation</a> to understand what this does. Of course this should only be done on GCC on Windows, so for portability you'll have to encapsulate this in a macro which you leave empty on other platforms. The advantage of this solution is that you can finely select which function might have a corrupted stack alignment. Of course on the downside this has to be done for every such function, so you may prefer one of the following two global solutions.
|
||||
|
||||
|
||||
\section sec_sol2 Global solutions
|
||||
|
||||
A global solution is to edit your project so that when compiling with GCC on Windows, you pass this option to GCC:
|
||||
\code
|
||||
-mpreferred-stack-boundary=3
|
||||
-mincoming-stack-boundary=2
|
||||
\endcode
|
||||
or
|
||||
Explanation: this tells GCC that the stack is only required to be aligned to 2^2=4 bytes, so that GCC now knows that it really must take extra care to honor the 16 byte alignment of \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types" when needed.
|
||||
|
||||
Another global solution is to pass this option to gcc:
|
||||
\code
|
||||
-mpreferred-stack-boundary=2
|
||||
-mstackrealign
|
||||
\endcode
|
||||
Explanation: this tells GCC that the stack should only be required to be aligned to 2^3=8 byes (in the first version) or to 2^2=4 bytes (in the second version). In both cases, this is smaller than 16 bytes, so GCC now knows that it really must take extra care to honor the 16 byte alignment of \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types". However, you must make sure that you understand fully what this does, before applying this change to your project. Read the GCC manual page. A too low value of \c -mpreferred-stack-boundary can result in poor performance: for example, on various CPUs, double-precision numbers work much faster when aligned to 8 bytes boundary, which is guaranteed by \c -mpreferred-stack-boundary=3 but not by \c -mpreferred-stack-boundary=2, so passing \c -mpreferred-stack-boundary=2 can result in poor performance! On the other hand, notice that the higher the value of \c -mpreferred-stack-boundary, the bigger the code size.
|
||||
which has the same effect than adding the \c force_align_arg_pointer attribute to all functions.
|
||||
|
||||
These global solutions are easy to use, but note that they may slowdown your program because they lead to extra prologue/epilogue instructions for every function.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ The solution is to let class Foo have an aligned "operator new", as we showed in
|
||||
|
||||
\section movetotop Should I then put all the members of Eigen types at the beginning of my class?
|
||||
|
||||
No, that's not needed. Since Eigen takes care of declaring 128-bit alignment, all members that need it are automatically 128-bit aligned relatively to the class. So when you have code like
|
||||
That's not required. Since Eigen takes care of declaring 128-bit alignment, all members that need it are automatically 128-bit aligned relatively to the class. So code like this works fine:
|
||||
|
||||
\code
|
||||
class Foo
|
||||
@@ -100,25 +100,13 @@ public:
|
||||
};
|
||||
\endcode
|
||||
|
||||
it will work just fine. You do \b not need to rewrite it as
|
||||
|
||||
\code
|
||||
class Foo
|
||||
{
|
||||
Eigen::Vector2d v;
|
||||
double x;
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
};
|
||||
\endcode
|
||||
|
||||
\section dynamicsize What about dynamic-size matrices and vectors?
|
||||
|
||||
Dynamic-size matrices and vectors, such as Eigen::VectorXd, allocate dynamically their own array of coefficients, so they take care of requiring absolute alignment automatically. So they don't cause this issue. The issue discussed here is only with fixed-size matrices and vectors.
|
||||
Dynamic-size matrices and vectors, such as Eigen::VectorXd, allocate dynamically their own array of coefficients, so they take care of requiring absolute alignment automatically. So they don't cause this issue. The issue discussed here is only with \ref FixedSizeVectorizable "fixed-size vectorizable matrices and vectors".
|
||||
|
||||
\section bugineigen So is this a bug in Eigen?
|
||||
|
||||
No, it's not our bug. It's more like an inherent problem of the C++ language -- though it must be said that any other existing language probably has the same problem. The problem is that there is no way that you can specify an aligned "operator new" that would propagate to classes having you as member data.
|
||||
No, it's not our bug. It's more like an inherent problem of the C++98 language specification, and seems to be taken care of in the upcoming language revision: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf">see this document</a>.
|
||||
|
||||
\section conditional What if I want to do this conditionnally (depending on template parameters) ?
|
||||
|
||||
|
||||
@@ -15,12 +15,24 @@ is explained here: http://eigen.tuxfamily.org/dox/UnalignedArrayAssert.html
|
||||
There are 3 known causes for this issue. Please read on to understand them and learn how to fix them.
|
||||
|
||||
\b Table \b of \b contents
|
||||
- \ref where
|
||||
- \ref c1
|
||||
- \ref c2
|
||||
- \ref c3
|
||||
- \ref c4
|
||||
- \ref explanation
|
||||
|
||||
\section where Where in my own code is the cause of the problem?
|
||||
|
||||
First of all, you need to find out where in your own code this assertion was triggered from. At first glance, the error message doesn't look helpful, as it refers to a file inside Eigen! However, since your program crashed, if you can reproduce the crash, you can get a backtrace using any debugger. For example, if you're using GCC, you can use the GDB debugger as follows:
|
||||
\code
|
||||
$ gdb ./my_program # Start GDB on your program
|
||||
> run # Start running your program
|
||||
... # Now reproduce the crash!
|
||||
> bt # Obtain the backtrace
|
||||
\endcode
|
||||
Now that you know precisely where in your own code the problem is happening, read on to understand what you need to change.
|
||||
|
||||
\section c1 Cause 1: Structures having Eigen objects as members
|
||||
|
||||
If you have code like this,
|
||||
|
||||
@@ -42,4 +42,10 @@ void test_product_large()
|
||||
m = (v+v).asDiagonal() * m;
|
||||
VERIFY_IS_APPROX(m, MatrixXf::Constant(N,3,2));
|
||||
}
|
||||
|
||||
{
|
||||
// test deferred resizing in Matrix::operator=
|
||||
MatrixXf a = MatrixXf::Random(10,4), b = MatrixXf::Random(4,10), c = a;
|
||||
VERIFY_IS_APPROX((a = a * b), (c * b).eval());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
# VERSION=opensuse-11.1
|
||||
# WORK_DIR=/home/gael/Coding/eigen2/cdash
|
||||
# # get the last version of the script
|
||||
# svn cat svn://anonsvn.kde.org/home/kde/trunk/kdesupport/eigen2/test/testsuite.cmake > $WORK_DIR/testsuite.cmake
|
||||
# wget http://bitbucket.org/eigen/eigen2/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
|
||||
@@ -132,11 +132,12 @@ endif(NOT EIGEN_MODE)
|
||||
|
||||
## mandatory variables (the default should be ok in most cases):
|
||||
|
||||
SET (CTEST_CVS_COMMAND "svn")
|
||||
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} co svn://anonsvn.kde.org/home/kde/trunk/kdesupport/eigen2 \"${CTEST_SOURCE_DIRECTORY}\"")
|
||||
SET (CTEST_CVS_COMMAND "hg")
|
||||
SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone -r 2.0 http://bitbucket.org/eigen/eigen2 \"${CTEST_SOURCE_DIRECTORY}\"")
|
||||
|
||||
# which ctest command to use for running the dashboard
|
||||
SET (CTEST_COMMAND "${EIGEN_CMAKE_DIR}ctest -D ${EIGEN_MODE}")
|
||||
|
||||
# what cmake command to use for configuring this dashboard
|
||||
SET (CTEST_CMAKE_COMMAND "${EIGEN_CMAKE_DIR}cmake -DEIGEN_BUILD_TESTS=on ")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user