Compare commits

...

13 Commits

Author SHA1 Message Date
Benoit Jacob
1eec8488a2 oops, placement new should take a void* 2009-01-05 19:56:32 +00:00
Benoit Jacob
9dcde48980 we also had to overload the placement new... issue uncovered by Tim when
doing QVector<Vector3d>...
2009-01-05 19:49:07 +00:00
Benoit Jacob
215ce5bdc1 forgot to install the LeastSquares header 2009-01-05 19:12:35 +00:00
Benoit Jacob
10f9478f35 release beta5, fix a doc typo 2009-01-05 19:00:10 +00:00
Benoit Jacob
9c8a653c0b gaaaaaaaaaaaaaaaaaah
can't believe that 3 people wasted so much time because of a missing &
!!!!!
and this time MSVC didn't catch it so it was really copying the vector
on the stack at an unaligned location!
2009-01-05 18:33:39 +00:00
Benoit Jacob
8551505436 problem solved, we really want public inheritance and it is only
automatic when the _child_ class is a struct.
2009-01-05 18:21:44 +00:00
Benoit Jacob
1b88042880 the empty base class optimization is not standard. Most compilers implement a basic form of it; however MSVC won't implement it if there is more than one empty base class.
For that reason, we shouldn't give Matrix two empty base classes, since sizeof(Matrix) must be optimal.
So we overload operator new and delete manually rather than inheriting an empty struct for doing that.
2009-01-05 16:46:19 +00:00
Benoit Jacob
7db3f2f72a *fix compilation with MSVC 2005 in the Transform::construct_from_matrix
*fix warnings with MSVC 2005: converting M_PI to float gives loss-of-precision warnings
2009-01-05 14:47:38 +00:00
Armin Berres
dae7f065d4 didn't meant to commit the fortran check. but anyway, unfortunately it doesn't work the way iot should. the test fails and cmake will terminate if it doesn't find a fortran compiler 2009-01-05 14:40:27 +00:00
Armin Berres
ab660a4d29 inherit from ei_with_aligned_operator_new even with disabled vectorization 2009-01-05 14:35:07 +00:00
Benoit Jacob
986f301233 *add PartialRedux::cross() with unit test
*add transform-from-matrices test
*undo an unwanted change in Matrix
2009-01-05 14:26:34 +00:00
Benoit Jacob
d316d4f393 fix compilation on apple: _mm_malloc was undefined. the fix is to just use malloc since on apple it already returns aligned ptrs 2009-01-05 13:15:27 +00:00
Benoit Jacob
e1ee876daa fix segfault due to non-aligned packets 2009-01-04 23:23:32 +00:00
16 changed files with 109 additions and 53 deletions

View File

@@ -1,5 +1,5 @@
project(Eigen) 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, #if the svnversion program is absent, this will leave the SVN_REVISION string empty,
#but won't stop CMake. #but won't stop CMake.

View File

@@ -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) if(EIGEN_BUILD_LIB)
set(Eigen_SRCS set(Eigen_SRCS

View File

@@ -172,6 +172,8 @@ template<typename ExpressionType, int Direction> class PartialRedux
> Type; > Type;
}; };
typedef typename ExpressionType::PlainMatrixType CrossReturnType;
inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {} inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
/** \internal */ /** \internal */
@@ -245,6 +247,32 @@ template<typename ExpressionType, int Direction> class PartialRedux
const typename ReturnType<ei_member_any>::Type any() const const typename ReturnType<ei_member_any>::Type any() const
{ return _expression(); } { 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: protected:
ExpressionTypeNested m_matrix; ExpressionTypeNested m_matrix;
}; };

View File

@@ -306,7 +306,7 @@ inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<
* *
* \only_for_vectors * \only_for_vectors
* *
* \sa dot(), normSquared() * \sa dot(), squaredNorm()
*/ */
template<typename Derived> template<typename Derived>
inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const inline typename NumTraits<typename ei_traits<Derived>::Scalar>::Real MatrixBase<Derived>::norm() const

View File

@@ -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> template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
class Matrix class Matrix
: public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > : public MatrixBase<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
, public ei_matrix_with_aligned_operator_new<_Scalar, _Rows, _Cols, _Options>
{ {
public: public:
EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix) EIGEN_GENERIC_PUBLIC_INTERFACE(Matrix)
@@ -140,6 +132,33 @@ class Matrix
protected: protected:
ei_matrix_storage<Scalar, MaxSizeAtCompileTime, RowsAtCompileTime, ColsAtCompileTime, Options> m_storage; 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: public:
EIGEN_STRONG_INLINE int rows() const { return m_storage.rows(); } EIGEN_STRONG_INLINE int rows() const { return m_storage.rows(); }

View File

@@ -56,6 +56,8 @@ inline T* ei_aligned_malloc(size_t size)
#else #else
#ifdef _MSC_VER #ifdef _MSC_VER
void_result = _aligned_malloc(size*sizeof(T), 16); 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 #else
void_result = _mm_malloc(size*sizeof(T), 16); void_result = _mm_malloc(size*sizeof(T), 16);
#endif #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! // 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 // so when we use C functions to allocate memory, we must be careful to call manually the constructor using
// the special placement-new syntax. // the special placement-new syntax.
return new(void_result) T[size]; return new(void_result) T[size];
} }
else else
return new T[size]; // here we really want a new, not a malloc. Justification: if the user uses Eigen on 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(); while(size) ptr[--size].~T();
#if defined(__linux) #if defined(__linux)
free(ptr); free(ptr);
#elif defined(__APPLE__)
free(ptr);
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
_aligned_free(ptr); _aligned_free(ptr);
#else #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. * overloading the operator new to return aligned data when the vectorization is enabled.
* Here is a similar safe example: * Here is a similar safe example:
* \code * \code
* struct Foo : WithAlignedOperatorNew { * struct Foo : public WithAlignedOperatorNew {
* char dummy; * char dummy;
* Vector4f some_vector; * Vector4f some_vector;
* }; * };
@@ -197,7 +201,7 @@ struct WithAlignedOperatorNew
template<typename T, int SizeAtCompileTime, template<typename T, int SizeAtCompileTime,
bool NeedsToAlign = (SizeAtCompileTime!=Dynamic) && ((sizeof(T)*SizeAtCompileTime)%16==0)> 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> template<typename T, int SizeAtCompileTime>
struct ei_with_aligned_operator_new<T,SizeAtCompileTime,false> {}; struct ei_with_aligned_operator_new<T,SizeAtCompileTime,false> {};

View File

@@ -39,9 +39,7 @@
*/ */
template <typename _Scalar, int _AmbientDim> template <typename _Scalar, int _AmbientDim>
class AlignedBox class AlignedBox
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1> : public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
#endif
{ {
public: public:
@@ -59,7 +57,7 @@ public:
{ setNull(); } { setNull(); }
/** Constructs a box with extremities \a _min and \a _max. */ /** 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. */ /** Constructs a box containing a single point \a p. */
inline explicit AlignedBox(const VectorType& p) : m_min(p), m_max(p) {} inline explicit AlignedBox(const VectorType& p) : m_min(p), m_max(p) {}

View File

@@ -45,9 +45,7 @@
*/ */
template <typename _Scalar, int _AmbientDim> template <typename _Scalar, int _AmbientDim>
class Hyperplane class Hyperplane
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1> : public ei_with_aligned_operator_new<_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1>
#endif
{ {
public: public:

View File

@@ -41,9 +41,7 @@
*/ */
template <typename _Scalar, int _AmbientDim> template <typename _Scalar, int _AmbientDim>
class ParametrizedLine class ParametrizedLine
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_AmbientDim> : public ei_with_aligned_operator_new<_Scalar,_AmbientDim>
#endif
{ {
public: public:

View File

@@ -59,9 +59,7 @@ template<typename _Scalar> struct ei_traits<Quaternion<_Scalar> >
template<typename _Scalar> template<typename _Scalar>
class Quaternion : public RotationBase<Quaternion<_Scalar>,3> class Quaternion : public RotationBase<Quaternion<_Scalar>,3>
#ifdef EIGEN_VECTORIZE
, public ei_with_aligned_operator_new<_Scalar,4> , public ei_with_aligned_operator_new<_Scalar,4>
#endif
{ {
typedef RotationBase<Quaternion<_Scalar>,3> Base; typedef RotationBase<Quaternion<_Scalar>,3> Base;
typedef Matrix<_Scalar, 4, 1> Coefficients; typedef Matrix<_Scalar, 4, 1> Coefficients;

View File

@@ -41,9 +41,7 @@
*/ */
template<typename _Scalar, int _Dim> template<typename _Scalar, int _Dim>
class Scaling class Scaling
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_Dim> : public ei_with_aligned_operator_new<_Scalar,_Dim>
#endif
{ {
public: public:
/** dimension of the space */ /** dimension of the space */

View File

@@ -61,9 +61,7 @@ struct ei_transform_product_impl;
*/ */
template<typename _Scalar, int _Dim> template<typename _Scalar, int _Dim>
class Transform class Transform
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1)> : public ei_with_aligned_operator_new<_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1)>
#endif
{ {
public: public:
@@ -108,7 +106,7 @@ public:
inline Transform& operator=(const Transform& other) inline Transform& operator=(const Transform& other)
{ m_matrix = other.m_matrix; return *this; } { 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 struct construct_from_matrix
{ {
static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other) static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
@@ -132,7 +130,7 @@ public:
template<typename OtherDerived> template<typename OtherDerived>
inline explicit Transform(const MatrixBase<OtherDerived>& other) 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. */ /** Set \c *this from a (Dim+1)^2 matrix. */

View File

@@ -41,9 +41,7 @@
*/ */
template<typename _Scalar, int _Dim> template<typename _Scalar, int _Dim>
class Translation class Translation
#ifdef EIGEN_VECTORIZE
: public ei_with_aligned_operator_new<_Scalar,_Dim> : public ei_with_aligned_operator_new<_Scalar,_Dim>
#endif
{ {
public: public:
/** dimension of the space */ /** dimension of the space */

View File

@@ -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: If you saw the assertion failure that links to this page, then you probably have done something like that in your code:
\code \code
struct Foo class Foo
{ {
... ...
Eigen::Vector2d v; Eigen::Vector2d v;
@@ -28,7 +28,7 @@ struct Foo
Foo *foo = new Foo; Foo *foo = new Foo;
\endcode \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: 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 \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? \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 \code
struct Foo : Eigen::WithAlignedOperatorNew class Foo : public Eigen::WithAlignedOperatorNew
{ {
... ...
Eigen::Vector2d v; 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: OK let's say that your code looks like this:
\code \code
struct Foo class Foo
{ {
... ...
Eigen::Vector2d v; 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... 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 \code
struct Foo : Eigen::WithAlignedOperatorNew class Foo : public Eigen::WithAlignedOperatorNew
{ {
double x; double x;
Eigen::Vector2d v; 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 it will work just fine. You do \b not need to rewrite it as
\code \code
struct Foo : Eigen::WithAlignedOperatorNew class Foo : public Eigen::WithAlignedOperatorNew
{ {
Eigen::Vector2d v; Eigen::Vector2d v;
double x; double x;

View File

@@ -59,7 +59,7 @@ template<typename Scalar> void geometry(void)
Vector2 u0 = Vector2::Random(); Vector2 u0 = Vector2::Random();
Matrix3 matrot1; Matrix3 matrot1;
Scalar a = ei_random<Scalar>(-M_PI, M_PI); Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
// cross product // cross product
VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1)); 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(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)); VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint(); m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized())); VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
@@ -88,8 +88,8 @@ template<typename Scalar> void geometry(void)
// angular distance // angular distance
Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle()); Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
if (refangle>M_PI) if (refangle>Scalar(M_PI))
refangle = 2.*M_PI - refangle; refangle = 2.*Scalar(M_PI) - refangle;
VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps)); VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
// rotation matrix conversion // rotation matrix conversion
@@ -138,7 +138,7 @@ template<typename Scalar> void geometry(void)
// TODO complete the tests ! // TODO complete the tests !
a = 0; a = 0;
while (ei_abs(a)<0.1) 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()); q1 = AngleAxisx(a, v0.normalized());
Transform3 t0, t1, t2; Transform3 t0, t1, t2;
t0.setIdentity(); t0.setIdentity();
@@ -181,7 +181,14 @@ template<typename Scalar> void geometry(void)
// More transform constructors, operator=, operator*= // 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(); Vector3 v3 = Vector3::Random().normalized();
AngleAxisx aa3(a3, v3); AngleAxisx aa3(a3, v3);
Transform3 t3(aa3); Transform3 t3(aa3);
@@ -388,6 +395,18 @@ template<typename Scalar> void geometry(void)
VERIFY_EULER(2,0,2, Z,X,Z); VERIFY_EULER(2,0,2, Z,X,Z);
VERIFY_EULER(2,1,0, Z,Y,X); VERIFY_EULER(2,1,0, Z,Y,X);
VERIFY_EULER(2,1,2, Z,Y,Z); 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() void test_geometry()

View File

@@ -61,10 +61,10 @@ template<typename Scalar> void packetmath()
const int PacketSize = ei_packet_traits<Scalar>::size; const int PacketSize = ei_packet_traits<Scalar>::size;
const int size = PacketSize*4; const int size = PacketSize*4;
Scalar data1[ei_packet_traits<Scalar>::size*4]; EIGEN_ALIGN_128 Scalar data1[ei_packet_traits<Scalar>::size*4];
Scalar data2[ei_packet_traits<Scalar>::size*4]; EIGEN_ALIGN_128 Scalar data2[ei_packet_traits<Scalar>::size*4];
Packet packets[PacketSize*2]; EIGEN_ALIGN_128 Packet packets[PacketSize*2];
Scalar ref[ei_packet_traits<Scalar>::size*4]; EIGEN_ALIGN_128 Scalar ref[ei_packet_traits<Scalar>::size*4];
for (int i=0; i<size; ++i) for (int i=0; i<size; ++i)
{ {
data1[i] = ei_random<Scalar>(); data1[i] = ei_random<Scalar>();