mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1eec8488a2 | ||
|
|
9dcde48980 | ||
|
|
215ce5bdc1 | ||
|
|
10f9478f35 | ||
|
|
9c8a653c0b | ||
|
|
8551505436 | ||
|
|
1b88042880 | ||
|
|
7db3f2f72a | ||
|
|
dae7f065d4 | ||
|
|
ab660a4d29 | ||
|
|
986f301233 | ||
|
|
d316d4f393 | ||
|
|
e1ee876daa |
@@ -1,5 +1,5 @@
|
||||
project(Eigen)
|
||||
set(EIGEN_VERSION_NUMBER "2.0-beta4")
|
||||
set(EIGEN_VERSION_NUMBER "2.0-beta5")
|
||||
|
||||
#if the svnversion program is absent, this will leave the SVN_REVISION string empty,
|
||||
#but won't stop CMake.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD Regression)
|
||||
set(Eigen_HEADERS Core LU Cholesky QR Geometry Sparse Array SVD Regression LeastSquares)
|
||||
|
||||
if(EIGEN_BUILD_LIB)
|
||||
set(Eigen_SRCS
|
||||
|
||||
@@ -172,6 +172,8 @@ template<typename ExpressionType, int Direction> class PartialRedux
|
||||
> Type;
|
||||
};
|
||||
|
||||
typedef typename ExpressionType::PlainMatrixType CrossReturnType;
|
||||
|
||||
inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
|
||||
|
||||
/** \internal */
|
||||
@@ -245,6 +247,32 @@ template<typename ExpressionType, int Direction> class PartialRedux
|
||||
const typename ReturnType<ei_member_any>::Type any() const
|
||||
{ return _expression(); }
|
||||
|
||||
/** \returns a 3x3 matrix expression of the cross product
|
||||
* of each column or row of the referenced expression with the \a other vector.
|
||||
*
|
||||
* \geometry_module
|
||||
*
|
||||
* \sa MatrixBase::cross() */
|
||||
template<typename OtherDerived>
|
||||
const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(CrossReturnType,3,3)
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
|
||||
EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
|
||||
if(Direction==Vertical)
|
||||
return (CrossReturnType()
|
||||
<< _expression().col(0).cross(other),
|
||||
_expression().col(1).cross(other),
|
||||
_expression().col(2).cross(other)).finished();
|
||||
else
|
||||
return (CrossReturnType()
|
||||
<< _expression().row(0).cross(other),
|
||||
_expression().row(1).cross(other),
|
||||
_expression().row(2).cross(other)).finished();
|
||||
}
|
||||
|
||||
protected:
|
||||
ExpressionTypeNested m_matrix;
|
||||
};
|
||||
|
||||
@@ -306,7 +306,7 @@ inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* \sa dot(), normSquared()
|
||||
* \sa dot(), squaredNorm()
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const
|
||||
|
||||
@@ -117,17 +117,9 @@ struct ei_traits<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T, int Rows, int Cols, int Options,
|
||||
bool NeedsToAlign = ((Options&Matrix_AutoAlign) == Matrix_AutoAlign) && Rows!=Dynamic && Cols!=Dynamic && ((sizeof(T)*Rows*Cols)%16==0)>
|
||||
struct ei_matrix_with_aligned_operator_new : WithAlignedOperatorNew {};
|
||||
|
||||
template<typename T, int Rows, int Cols, int Options>
|
||||
struct ei_matrix_with_aligned_operator_new<T, Rows, Cols, Options, false> {};
|
||||
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
|
||||
class Matrix
|
||||
: public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
|
||||
, public ei_matrix_with_aligned_operator_new<_Scalar, _Rows, _Cols, _Options>
|
||||
{
|
||||
public:
|
||||
EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix)
|
||||
@@ -140,6 +132,33 @@ class Matrix
|
||||
protected:
|
||||
ei_matrix_storage<Scalar, MaxSizeAtCompileTime, RowsAtCompileTime, ColsAtCompileTime, Options> m_storage;
|
||||
|
||||
public:
|
||||
enum { NeedsToAlign = (Options&Matrix_AutoAlign) == Matrix_AutoAlign
|
||||
&& SizeAtCompileTime!=Dynamic && ((sizeof(Scalar)*SizeAtCompileTime)%16)==0 };
|
||||
typedef typename ei_meta_if<NeedsToAlign, ei_byte_forcing_aligned_malloc, char>::ret ByteAlignedAsNeeded;
|
||||
void *operator new(size_t size) throw()
|
||||
{
|
||||
return ei_aligned_malloc<ByteAlignedAsNeeded>(size);
|
||||
}
|
||||
|
||||
void *operator new(size_t, void *ptr) throw()
|
||||
{
|
||||
return static_cast<void*>(ptr);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size) throw()
|
||||
{
|
||||
return ei_aligned_malloc<ByteAlignedAsNeeded>(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t, void *ptr) throw()
|
||||
{
|
||||
return static_cast<void*>(ptr);
|
||||
}
|
||||
|
||||
void operator delete(void * ptr) { ei_aligned_free(static_cast<ByteAlignedAsNeeded *>(ptr), 0); }
|
||||
void operator delete[](void * ptr) { ei_aligned_free(static_cast<ByteAlignedAsNeeded *>(ptr), 0); }
|
||||
|
||||
public:
|
||||
|
||||
EIGEN_STRONG_INLINE int rows() const { return m_storage.rows(); }
|
||||
|
||||
@@ -56,6 +56,8 @@ inline T* ei_aligned_malloc(size_t size)
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
void_result = _aligned_malloc(size*sizeof(T), 16);
|
||||
#elif defined(__APPLE__)
|
||||
void_result = malloc(size*sizeof(T)); // Apple's malloc() already returns aligned ptrs
|
||||
#else
|
||||
void_result = _mm_malloc(size*sizeof(T), 16);
|
||||
#endif
|
||||
@@ -71,7 +73,7 @@ inline T* ei_aligned_malloc(size_t size)
|
||||
// and this type has a custom operator new, then we want to honor this operator new!
|
||||
// so when we use C functions to allocate memory, we must be careful to call manually the constructor using
|
||||
// the special placement-new syntax.
|
||||
return new(void_result) T[size];
|
||||
return new(void_result) T[size];
|
||||
}
|
||||
else
|
||||
return new T[size]; // here we really want a new, not a malloc. Justification: if the user uses Eigen on
|
||||
@@ -95,6 +97,8 @@ inline void ei_aligned_free(T* ptr, size_t size)
|
||||
while(size) ptr[--size].~T();
|
||||
#if defined(__linux)
|
||||
free(ptr);
|
||||
#elif defined(__APPLE__)
|
||||
free(ptr);
|
||||
#elif defined(_MSC_VER)
|
||||
_aligned_free(ptr);
|
||||
#else
|
||||
@@ -169,7 +173,7 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
|
||||
* overloading the operator new to return aligned data when the vectorization is enabled.
|
||||
* Here is a similar safe example:
|
||||
* \code
|
||||
* struct Foo : WithAlignedOperatorNew {
|
||||
* struct Foo : public WithAlignedOperatorNew {
|
||||
* char dummy;
|
||||
* Vector4f some_vector;
|
||||
* };
|
||||
@@ -197,7 +201,7 @@ struct WithAlignedOperatorNew
|
||||
|
||||
template<typename T, int SizeAtCompileTime,
|
||||
bool NeedsToAlign = (SizeAtCompileTime!=Dynamic) && ((sizeof(T)*SizeAtCompileTime)%16==0)>
|
||||
struct ei_with_aligned_operator_new : WithAlignedOperatorNew {};
|
||||
struct ei_with_aligned_operator_new : public WithAlignedOperatorNew {};
|
||||
|
||||
template<typename T, int SizeAtCompileTime>
|
||||
struct ei_with_aligned_operator_new<T,SizeAtCompileTime,false> {};
|
||||
|
||||
@@ -39,9 +39,7 @@
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class AlignedBox
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -59,7 +57,7 @@ public:
|
||||
{ setNull(); }
|
||||
|
||||
/** Constructs a box with extremities \a _min and \a _max. */
|
||||
inline AlignedBox(const VectorType& _min, const VectorType _max) : m_min(_min), m_max(_max) {}
|
||||
inline AlignedBox(const VectorType& _min, const VectorType& _max) : m_min(_min), m_max(_max) {}
|
||||
|
||||
/** Constructs a box containing a single point \a p. */
|
||||
inline explicit AlignedBox(const VectorType& p) : m_min(p), m_max(p) {}
|
||||
|
||||
@@ -45,9 +45,7 @@
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class Hyperplane
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
@@ -41,9 +41,7 @@
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class ParametrizedLine
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
@@ -59,9 +59,7 @@ template<typename _Scalar> struct ei_traits<Quaternion<_Scalar> >
|
||||
|
||||
template<typename _Scalar>
|
||||
class Quaternion : public RotationBase<Quaternion<_Scalar>,3>
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
, public ei_with_aligned_operator_new<_Scalar,4>
|
||||
#endif
|
||||
{
|
||||
typedef RotationBase<Quaternion<_Scalar>,3> Base;
|
||||
typedef Matrix<_Scalar, 4, 1> Coefficients;
|
||||
|
||||
@@ -41,9 +41,7 @@
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Scaling
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_Dim>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/** dimension of the space */
|
||||
|
||||
@@ -61,9 +61,7 @@ struct ei_transform_product_impl;
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Transform
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1)>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -108,7 +106,7 @@ public:
|
||||
inline Transform& operator=(const Transform& other)
|
||||
{ m_matrix = other.m_matrix; return *this; }
|
||||
|
||||
template<typename OtherDerived, bool select = OtherDerived::RowsAtCompileTime == Dim>
|
||||
template<typename OtherDerived, bool BigMatrix> // MSVC 2005 will commit suicide if BigMatrix has a default value
|
||||
struct construct_from_matrix
|
||||
{
|
||||
static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
|
||||
@@ -132,7 +130,7 @@ public:
|
||||
template<typename OtherDerived>
|
||||
inline explicit Transform(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
construct_from_matrix<OtherDerived>::run(this, other);
|
||||
construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other);
|
||||
}
|
||||
|
||||
/** Set \c *this from a (Dim+1)^2 matrix. */
|
||||
|
||||
@@ -41,9 +41,7 @@
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Translation
|
||||
#ifdef EIGEN_VECTORIZE
|
||||
: public ei_with_aligned_operator_new<_Scalar,_Dim>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
/** dimension of the space */
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Eigen {
|
||||
If you saw the assertion failure that links to this page, then you probably have done something like that in your code:
|
||||
|
||||
\code
|
||||
struct Foo
|
||||
class Foo
|
||||
{
|
||||
...
|
||||
Eigen::Vector2d v;
|
||||
@@ -28,7 +28,7 @@ struct Foo
|
||||
Foo *foo = new Foo;
|
||||
\endcode
|
||||
|
||||
In other words: you have probably in your code a structure that has as a member a vectorizable fixed-size Eigen object, and you then dynamically allocated an object of that structure.
|
||||
In other words: you have probably in your code a class that has as a member a vectorizable fixed-size Eigen object, and you then dynamically allocated an object of that class.
|
||||
|
||||
By "vectorizable fixed-size Eigen object" we mean an Eigen matrix or vector of fixed size, and whose size is a multiple of 128 bits. Examples include:
|
||||
\li Eigen::Vector2d
|
||||
@@ -43,10 +43,10 @@ By "vectorizable fixed-size Eigen object" we mean an Eigen matrix or vector of f
|
||||
|
||||
\section how How to fix this bug?
|
||||
|
||||
Very easy, you just need to let your struct Foo inherit Eigen::WithAlignedOperatorNew, like this:
|
||||
Very easy, you just need to let your class Foo publicly inherit Eigen::WithAlignedOperatorNew, like this:
|
||||
|
||||
\code
|
||||
struct Foo : Eigen::WithAlignedOperatorNew
|
||||
class Foo : public Eigen::WithAlignedOperatorNew
|
||||
{
|
||||
...
|
||||
Eigen::Vector2d v;
|
||||
@@ -65,7 +65,7 @@ With this, you should be out of trouble.
|
||||
OK let's say that your code looks like this:
|
||||
|
||||
\code
|
||||
struct Foo
|
||||
class Foo
|
||||
{
|
||||
...
|
||||
Eigen::Vector2d v;
|
||||
@@ -85,18 +85,18 @@ For this reason, Eigen takes care by itself to require 128-bit alignment for Eig
|
||||
|
||||
Thus, normally, you don't have to worry about anything, Eigen handles alignment for you...
|
||||
|
||||
... except in one case. When you have a struct Foo like above, and you dynamically allocate a new Foo as above, then, since Foo doesn't have aligned "operator new", the returned pointer foo is not necessarily 128-bit aligned.
|
||||
... except in one case. When you have a class Foo like above, and you dynamically allocate a new Foo as above, then, since Foo doesn't have aligned "operator new", the returned pointer foo is not necessarily 128-bit aligned.
|
||||
|
||||
The alignment attribute of the member v is then relative to the start of the struct, foo. If the foo pointer wasn't aligned, then foo->v won't be aligned either!
|
||||
The alignment attribute of the member v is then relative to the start of the class, foo. If the foo pointer wasn't aligned, then foo->v won't be aligned either!
|
||||
|
||||
The solution is to let struct Foo have an aligned "operator new", as we showed in the previous section.
|
||||
The solution is to let class Foo have an aligned "operator new", as we showed in the previous section.
|
||||
|
||||
\section movetotop Should I then put all the members of Eigen types at the beginning of my struct?
|
||||
\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 struct. So when you have code like
|
||||
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
|
||||
|
||||
\code
|
||||
struct Foo : Eigen::WithAlignedOperatorNew
|
||||
class Foo : public Eigen::WithAlignedOperatorNew
|
||||
{
|
||||
double x;
|
||||
Eigen::Vector2d v;
|
||||
@@ -106,7 +106,7 @@ struct Foo : Eigen::WithAlignedOperatorNew
|
||||
it will work just fine. You do \b not need to rewrite it as
|
||||
|
||||
\code
|
||||
struct Foo : Eigen::WithAlignedOperatorNew
|
||||
class Foo : public Eigen::WithAlignedOperatorNew
|
||||
{
|
||||
Eigen::Vector2d v;
|
||||
double x;
|
||||
|
||||
@@ -59,7 +59,7 @@ template<typename Scalar> void geometry(void)
|
||||
Vector2 u0 = Vector2::Random();
|
||||
Matrix3 matrot1;
|
||||
|
||||
Scalar a = ei_random<Scalar>(-M_PI, M_PI);
|
||||
Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
|
||||
|
||||
// cross product
|
||||
VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1));
|
||||
@@ -77,7 +77,7 @@ template<typename Scalar> void geometry(void)
|
||||
|
||||
|
||||
VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
|
||||
VERIFY_IS_APPROX(-v0, AngleAxisx(M_PI, v0.unitOrthogonal()) * v0);
|
||||
VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
|
||||
VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
|
||||
m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
|
||||
VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
|
||||
@@ -88,8 +88,8 @@ template<typename Scalar> void geometry(void)
|
||||
|
||||
// angular distance
|
||||
Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
|
||||
if (refangle>M_PI)
|
||||
refangle = 2.*M_PI - refangle;
|
||||
if (refangle>Scalar(M_PI))
|
||||
refangle = 2.*Scalar(M_PI) - refangle;
|
||||
VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
|
||||
|
||||
// rotation matrix conversion
|
||||
@@ -138,7 +138,7 @@ template<typename Scalar> void geometry(void)
|
||||
// TODO complete the tests !
|
||||
a = 0;
|
||||
while (ei_abs(a)<0.1)
|
||||
a = ei_random<Scalar>(-0.4*M_PI, 0.4*M_PI);
|
||||
a = ei_random<Scalar>(-0.4*Scalar(M_PI), 0.4*Scalar(M_PI));
|
||||
q1 = AngleAxisx(a, v0.normalized());
|
||||
Transform3 t0, t1, t2;
|
||||
t0.setIdentity();
|
||||
@@ -181,7 +181,14 @@ template<typename Scalar> void geometry(void)
|
||||
|
||||
// More transform constructors, operator=, operator*=
|
||||
|
||||
Scalar a3 = ei_random<Scalar>(-M_PI, M_PI);
|
||||
Matrix3 mat3 = Matrix3::Random();
|
||||
Matrix4 mat4;
|
||||
mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
|
||||
Transform3 tmat3(mat3), tmat4(mat4);
|
||||
tmat4.matrix()(3,3) = Scalar(1);
|
||||
VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
|
||||
|
||||
Scalar a3 = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
|
||||
Vector3 v3 = Vector3::Random().normalized();
|
||||
AngleAxisx aa3(a3, v3);
|
||||
Transform3 t3(aa3);
|
||||
@@ -388,6 +395,18 @@ template<typename Scalar> void geometry(void)
|
||||
VERIFY_EULER(2,0,2, Z,X,Z);
|
||||
VERIFY_EULER(2,1,0, Z,Y,X);
|
||||
VERIFY_EULER(2,1,2, Z,Y,Z);
|
||||
|
||||
// colwise/rowwise cross product
|
||||
mat3.setRandom();
|
||||
Vector3 vec3 = Vector3::Random();
|
||||
Matrix3 mcross;
|
||||
int i = ei_random<int>(0,2);
|
||||
mcross = mat3.colwise().cross(vec3);
|
||||
VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
|
||||
mcross = mat3.rowwise().cross(vec3);
|
||||
VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void test_geometry()
|
||||
|
||||
@@ -61,10 +61,10 @@ template<typename Scalar> void packetmath()
|
||||
const int PacketSize = ei_packet_traits<Scalar>::size;
|
||||
|
||||
const int size = PacketSize*4;
|
||||
Scalar data1[ei_packet_traits<Scalar>::size*4];
|
||||
Scalar data2[ei_packet_traits<Scalar>::size*4];
|
||||
Packet packets[PacketSize*2];
|
||||
Scalar ref[ei_packet_traits<Scalar>::size*4];
|
||||
EIGEN_ALIGN_128 Scalar data1[ei_packet_traits<Scalar>::size*4];
|
||||
EIGEN_ALIGN_128 Scalar data2[ei_packet_traits<Scalar>::size*4];
|
||||
EIGEN_ALIGN_128 Packet packets[PacketSize*2];
|
||||
EIGEN_ALIGN_128 Scalar ref[ei_packet_traits<Scalar>::size*4];
|
||||
for (int i=0; i<size; ++i)
|
||||
{
|
||||
data1[i] = ei_random<Scalar>();
|
||||
|
||||
Reference in New Issue
Block a user