diff --git a/Eigen/StdVector b/Eigen/StdVector index e8b5354ac..eedea750e 100644 --- a/Eigen/StdVector +++ b/Eigen/StdVector @@ -1,15 +1,133 @@ #ifndef EIGEN_STDVECTOR_MODULE_H #define EIGEN_STDVECTOR_MODULE_H -#include "Core" -#include +#if defined(_GLIBCXX_VECTOR) || defined(_VECTOR_) +#error you must include Eigen/StdVector before std::vector +#endif + +#ifndef EIGEN_GNUC_AT_LEAST +#ifdef __GNUC__ + #define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__>=x && __GNUC_MINOR__>=y) || __GNUC__>x) +#else + #define EIGEN_GNUC_AT_LEAST(x,y) 0 +#endif +#endif + +#define vector std_vector +#include +#undef vector namespace Eigen { -#include "src/StdVector/UnalignedType.h" -} // namespace Eigen + +template class aligned_allocator; + +// meta programming to determine if a class has a given member +struct ei_does_not_have_aligned_operator_new_marker_sizeof {int a[1];}; +struct ei_has_aligned_operator_new_marker_sizeof {int a[2];}; + +template +struct ei_has_aligned_operator_new { + template + static ei_has_aligned_operator_new_marker_sizeof + test(T const *, typename T::ei_operator_new_marker_type const * = 0); + static ei_does_not_have_aligned_operator_new_marker_sizeof + test(...); + + // note that the following indirection is needed for gcc-3.3 + enum {ret = sizeof(test(static_cast(0))) + == sizeof(ei_has_aligned_operator_new_marker_sizeof) }; +}; + +#ifdef _MSC_VER + + // sometimes, MSVC detects, at compile time, that the argument x + // in std::vector::resize(size_t s,T x) won't be aligned and generate an error + // even if this function is never called. Whence this little wrapper. + #define _EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) Eigen::ei_workaround_msvc_std_vector + template struct ei_workaround_msvc_std_vector : public T + { + inline ei_workaround_msvc_std_vector() : T() {} + inline ei_workaround_msvc_std_vector(const T& other) : T(other) {} + inline operator T& () { return *static_cast(this); } + inline operator const T& () const { return *static_cast(this); } + template + inline T& operator=(const OtherT& other) + { T::operator=(other); return *this; } + inline ei_workaround_msvc_std_vector& operator=(const ei_workaround_msvc_std_vector& other) + { T::operator=(other); return *this; } + }; + +#else + + #define _EIGEN_WORKAROUND_MSVC_STD_VECTOR(T) T + +#endif + +} namespace std { -#include "src/StdVector/StdVector.h" -} // namespace std + +#define EIGEN_STD_VECTOR_SPECIALIZATION_BODY \ + public: \ + typedef T value_type; \ + typedef typename vector_base::allocator_type allocator_type; \ + typedef typename vector_base::size_type size_type; \ + typedef typename vector_base::iterator iterator; \ + explicit vector(const allocator_type& __a = allocator_type()) : vector_base(__a) {} \ + vector(const vector& c) : vector_base(c) {} \ + vector(size_type num, const value_type& val = value_type()) : vector_base(num, val) {} \ + vector(iterator start, iterator end) : vector_base(start, end) {} \ + vector& operator=(const vector& __x) { \ + vector_base::operator=(__x); \ + return *this; \ + } + +template, + bool HasAlignedNew = Eigen::ei_has_aligned_operator_new::ret> +class vector : public std::std_vector +{ + typedef std_vector vector_base; + EIGEN_STD_VECTOR_SPECIALIZATION_BODY +}; + +template +class vector + : public std::std_vector<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T), + Eigen::aligned_allocator<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> > +{ + typedef std_vector<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T), + Eigen::aligned_allocator<_EIGEN_WORKAROUND_MSVC_STD_VECTOR(T)> > vector_base; + EIGEN_STD_VECTOR_SPECIALIZATION_BODY + + void resize(size_type __new_size) + { resize(__new_size, T()); } + + #if defined(_VECTOR_) + // workaround MSVC std::vector implementation + void resize(size_type __new_size, const value_type& __x) + { + if (vector_base::size() < __new_size) + vector_base::_Insert_n(vector_base::end(), __new_size - vector_base::size(), __x); + else if (__new_size < vector_base::size()) + vector_base::erase(vector_base::begin() + __new_size, vector_base::end()); + } + #elif defined(_GLIBCXX_VECTOR) && EIGEN_GNUC_AT_LEAST(4,1) + // workaround GCC std::vector implementation + // Note that before gcc-4.1 we already have: std::vector::resize(size_type,const T&), + // no no need to workaround ! + void resize(size_type __new_size, const value_type& __x) + { + if (__new_size < vector_base::size()) + vector_base::_M_erase_at_end(this->_M_impl._M_start + __new_size); + else + vector_base::insert(vector_base::end(), __new_size - vector_base::size(), __x); + } + #else + using vector_base::resize; + #endif +}; + +} #endif // EIGEN_STDVECTOR_MODULE_H diff --git a/Eigen/src/CMakeLists.txt b/Eigen/src/CMakeLists.txt index b244809d6..e6832e850 100644 --- a/Eigen/src/CMakeLists.txt +++ b/Eigen/src/CMakeLists.txt @@ -7,4 +7,3 @@ ADD_SUBDIRECTORY(Array) ADD_SUBDIRECTORY(Geometry) ADD_SUBDIRECTORY(LeastSquares) ADD_SUBDIRECTORY(Sparse) -ADD_SUBDIRECTORY(StdVector) diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index cfbf6da53..195533266 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -221,15 +221,13 @@ class Block class InnerIterator; typedef typename ei_traits::AlignedDerivedType AlignedDerivedType; + friend class Block; EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) - AlignedDerivedType forceAligned() + AlignedDerivedType _convertToForceAligned() { - if (PacketAccess==ForceAligned) - return *this; - else - return Block + return Block (m_matrix, Base::m_data, Base::m_rows.value(), Base::m_cols.value()); } @@ -454,7 +452,7 @@ MatrixBase::end(int size) const * \only_for_vectors * * The template parameter \a Size is the number of coefficients in the block - * + * * \param start the index of the first element of the sub-vector * * Example: \include MatrixBase_template_int_segment.cpp diff --git a/Eigen/src/Core/Map.h b/Eigen/src/Core/Map.h index 5fe13005f..5f44a87e6 100644 --- a/Eigen/src/Core/Map.h +++ b/Eigen/src/Core/Map.h @@ -66,12 +66,9 @@ template class Map inline int stride() const { return this->innerSize(); } - AlignedDerivedType forceAligned() + AlignedDerivedType _convertToForceAligned() { - if (PacketAccess==ForceAligned) - return *this; - else - return Map(Base::m_data, Base::m_rows.value(), Base::m_cols.value()); + return Map(Base::m_data, Base::m_rows.value(), Base::m_cols.value()); } inline Map(const Scalar* data) : Base(data) {} diff --git a/Eigen/src/Core/MapBase.h b/Eigen/src/Core/MapBase.h index 7014f27f6..c923bc340 100644 --- a/Eigen/src/Core/MapBase.h +++ b/Eigen/src/Core/MapBase.h @@ -65,9 +65,20 @@ template class MapBase inline int stride() const { return derived().stride(); } inline const Scalar* data() const { return m_data; } + template struct force_aligned_impl { + AlignedDerivedType static run(MapBase& a) { return a.derived(); } + }; + + template struct force_aligned_impl { + AlignedDerivedType static run(MapBase& a) { return a.derived()._convertToForceAligned(); } + }; + /** \returns an expression equivalent to \c *this but having the \c PacketAccess constant * set to \c ForceAligned. Must be reimplemented by the derived class. */ - AlignedDerivedType forceAligned() { return derived().forceAligned(); } + AlignedDerivedType forceAligned() + { + return force_aligned_impl::run(*this); + } inline const Scalar& coeff(int row, int col) const { @@ -155,6 +166,19 @@ template class MapBase && cols > 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols))); } + Derived& operator=(const MapBase& other) + { + return Base::operator=(other); + } + + template + Derived& operator=(const MatrixBase& other) + { + return Base::operator=(other); + } + + using Base::operator*=; + template Derived& operator+=(const MatrixBase& other) { return derived() = forceAligned() + other; } diff --git a/Eigen/src/Core/Matrix.h b/Eigen/src/Core/Matrix.h index 48aad9a65..9f87d31fc 100644 --- a/Eigen/src/Core/Matrix.h +++ b/Eigen/src/Core/Matrix.h @@ -226,7 +226,6 @@ class Matrix */ inline void resize(int rows, int cols) { - ei_assert(rows > 0 && cols > 0 && "a matrix cannot be resized to 0 size"); ei_assert((MaxRowsAtCompileTime == Dynamic || MaxRowsAtCompileTime >= rows) && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) && (MaxColsAtCompileTime == Dynamic || MaxColsAtCompileTime >= cols) @@ -240,7 +239,6 @@ class Matrix */ inline void resize(int size) { - ei_assert(size>0 && "a vector cannot be resized to 0 length"); EIGEN_STATIC_ASSERT_VECTOR_ONLY(Matrix) if(RowsAtCompileTime == 1) m_storage.resize(size, 1, size); diff --git a/Eigen/src/Core/MatrixStorage.h b/Eigen/src/Core/MatrixStorage.h index ce656f13b..ba2355b8e 100644 --- a/Eigen/src/Core/MatrixStorage.h +++ b/Eigen/src/Core/MatrixStorage.h @@ -176,7 +176,10 @@ template class ei_matrix_storage(size); + if (size) + m_data = ei_aligned_new(size); + else + m_data = 0; } m_rows = rows; m_cols = cols; @@ -203,7 +206,10 @@ template class ei_matrix_storage(size); + if (size) + m_data = ei_aligned_new(size); + else + m_data = 0; } m_cols = cols; } @@ -229,7 +235,10 @@ template class ei_matrix_storage(size); + if (size) + m_data = ei_aligned_new(size); + else + m_data = 0; } m_rows = rows; } diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h index fe29007c4..2e2c4638a 100644 --- a/Eigen/src/Core/util/Macros.h +++ b/Eigen/src/Core/util/Macros.h @@ -193,18 +193,18 @@ using Eigen::ei_cos; template \ EIGEN_STRONG_INLINE Derived& operator Op(const Eigen::MatrixBase& other) \ { \ - return Eigen::MatrixBase::operator Op(other.derived()); \ + return Base::operator Op(other.derived()); \ } \ EIGEN_STRONG_INLINE Derived& operator Op(const Derived& other) \ { \ - return Eigen::MatrixBase::operator Op(other); \ + return Base::operator Op(other); \ } #define EIGEN_INHERIT_SCALAR_ASSIGNMENT_OPERATOR(Derived, Op) \ template \ EIGEN_STRONG_INLINE Derived& operator Op(const Other& scalar) \ { \ - return Eigen::MatrixBase::operator Op(scalar); \ + return Base::operator Op(scalar); \ } #define EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Derived) \ diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 8c58debea..c3504d549 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -247,7 +247,8 @@ inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset) } \ void operator delete(void * ptr) { Eigen::ei_conditional_aligned_free(ptr); } \ void operator delete[](void * ptr) { Eigen::ei_conditional_aligned_free(ptr); } \ - void *operator new(size_t, void *ptr) throw() { return ptr; } + void *operator new(size_t, void *ptr) throw() { return ptr; } \ + typedef void ei_operator_new_marker_type; #else #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) #endif @@ -288,34 +289,34 @@ public: typedef aligned_allocator other; }; - pointer address( reference value ) const + pointer address( reference value ) const { return &value; } - const_pointer address( const_reference value ) const + const_pointer address( const_reference value ) const { return &value; } - aligned_allocator() throw() + aligned_allocator() throw() { } - aligned_allocator( const aligned_allocator& ) throw() + aligned_allocator( const aligned_allocator& ) throw() { } template - aligned_allocator( const aligned_allocator& ) throw() + aligned_allocator( const aligned_allocator& ) throw() { } - ~aligned_allocator() throw() + ~aligned_allocator() throw() { } - size_type max_size() const throw() + size_type max_size() const throw() { return std::numeric_limits::max(); } @@ -326,17 +327,17 @@ public: return static_cast( ei_aligned_malloc( num * sizeof(T) ) ); } - void construct( pointer p, const T& value ) + void construct( pointer p, const T& value ) { ::new( p ) T( value ); } - void destroy( pointer p ) + void destroy( pointer p ) { p->~T(); } - void deallocate( pointer p, size_type /*num*/ ) + void deallocate( pointer p, size_type /*num*/ ) { ei_aligned_free( p ); } diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h index ce6e60868..3be4ccbca 100644 --- a/Eigen/src/Geometry/Quaternion.h +++ b/Eigen/src/Geometry/Quaternion.h @@ -61,12 +61,12 @@ template class Quaternion : public RotationBase,3> { typedef RotationBase,3> Base; - + public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,4) using Base::operator*; - + /** the scalar type of the coefficients */ typedef _Scalar Scalar; @@ -112,10 +112,6 @@ public: /** Default constructor leaving the quaternion uninitialized. */ inline Quaternion() {} - inline Quaternion(ei_constructor_without_unaligned_array_assert) - : m_coeffs(ei_constructor_without_unaligned_array_assert()) {} - - /** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from * its four coefficients \a w, \a x, \a y and \a z. * @@ -217,7 +213,7 @@ public: bool isApprox(const Quaternion& other, typename NumTraits::Real prec = precision()) const { return m_coeffs.isApprox(other.m_coeffs, prec); } -protected: +protected: Coefficients m_coeffs; }; diff --git a/Eigen/src/Geometry/Transform.h b/Eigen/src/Geometry/Transform.h index 9b3e1b655..a796ba792 100644 --- a/Eigen/src/Geometry/Transform.h +++ b/Eigen/src/Geometry/Transform.h @@ -95,11 +95,8 @@ public: /** Default constructor without initialization of the coefficients. */ inline Transform() { } - inline Transform(ei_constructor_without_unaligned_array_assert) - : m_matrix(ei_constructor_without_unaligned_array_assert()) {} - inline Transform(const Transform& other) - { + { m_matrix = other.m_matrix; } @@ -648,7 +645,7 @@ template template void Transform::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const { - linear().svd().computeScalingRotation(scaling, rotation); + linear().svd().computeScalingRotation(scaling, rotation); } /** Convenient method to set \c *this from a position, orientation and scale diff --git a/Eigen/src/StdVector/CMakeLists.txt b/Eigen/src/StdVector/CMakeLists.txt deleted file mode 100644 index 7be6c00a6..000000000 --- a/Eigen/src/StdVector/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -FILE(GLOB Eigen_StdVector_SRCS "*.h") - -INSTALL(FILES - ${Eigen_StdVector_SRCS} - DESTINATION ${INCLUDE_INSTALL_DIR}/Eigen/src/StdVector - ) diff --git a/Eigen/src/StdVector/StdVector.h b/Eigen/src/StdVector/StdVector.h deleted file mode 100644 index a45036736..000000000 --- a/Eigen/src/StdVector/StdVector.h +++ /dev/null @@ -1,73 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. Eigen itself is part of the KDE project. -// -// Copyright (C) 2009 Benoit Jacob -// Copyright (C) 2009 Alex Stapleton -// -// 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 . - -#ifndef EIGEN_STDVECTOR_H -#define EIGEN_STDVECTOR_H - -#define EIGEN_STD_VECTOR_SPECIALIZATION_BODY \ - typedef Eigen::aligned_allocator allocator_type; \ - typedef vector unaligned_base; \ - typedef typename unaligned_base::size_type size_type; \ - typedef typename unaligned_base::iterator iterator; \ - explicit vector(const allocator_type& __a = allocator_type()) : unaligned_base(__a) {} \ - vector(const vector& c) : unaligned_base(c) {} \ - vector(size_type num, const value_type& val = value_type()) : unaligned_base(num, val) {}\ - vector(iterator start, iterator end) : unaligned_base(start, end) {} \ - vector& operator=(const vector& __x) { \ - unaligned_base::operator=(__x); \ - return *this; \ - } - -template -class vector, _Alloc> - : public vector >, - Eigen::aligned_allocator > > > -{ -public: - typedef Eigen::ei_unaligned_type > value_type; - EIGEN_STD_VECTOR_SPECIALIZATION_BODY -}; - -template -class vector, _Alloc> - : public vector >, - Eigen::aligned_allocator > > > -{ -public: - typedef Eigen::ei_unaligned_type > value_type; - EIGEN_STD_VECTOR_SPECIALIZATION_BODY -}; - -template -class vector, _Alloc> - : public vector >, - Eigen::aligned_allocator > > > -{ -public: - typedef Eigen::ei_unaligned_type > value_type; - EIGEN_STD_VECTOR_SPECIALIZATION_BODY -}; - -#endif // EIGEN_STDVECTOR_H diff --git a/Eigen/src/StdVector/UnalignedType.h b/Eigen/src/StdVector/UnalignedType.h deleted file mode 100644 index c67e3d905..000000000 --- a/Eigen/src/StdVector/UnalignedType.h +++ /dev/null @@ -1,105 +0,0 @@ -// This file is part of Eigen, a lightweight C++ template library -// for linear algebra. Eigen itself is part of the KDE project. -// -// Copyright (C) 2009 Benoit Jacob -// Copyright (C) 2009 Alex Stapleton -// -// 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 . - -#ifndef EIGEN_UNALIGNEDTYPE_H -#define EIGEN_UNALIGNEDTYPE_H - -template class ei_unaligned_type; - -template -class ei_unaligned_type > - : public Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> -{ - private: - template void _unaligned_copy(const Other& other) - { - if(other.size() == 0) return; - resize(other.rows(), other.cols()); - ei_assign_impl::run(*this, other); - } - - public: - typedef Matrix<_Scalar,_Rows,_Cols,_Options,_MaxRows,_MaxCols> aligned_base; - ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {} - ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert()) - { - _unaligned_copy(other); - } - ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert()) - { - _unaligned_copy(other); - } -}; - -template -class ei_unaligned_type > - : public Transform<_Scalar,_Dim> -{ - private: - template void _unaligned_copy(const Other& other) - { - // no resizing here, it's fixed-size anyway - ei_assign_impl::run(this->matrix(), other.matrix()); - } - public: - typedef Transform<_Scalar,_Dim> aligned_base; - typedef typename aligned_base::MatrixType MatrixType; - ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {} - ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert()) - { - _unaligned_copy(other); - } - ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert()) - { - _unaligned_copy(other); - } -}; - -template -class ei_unaligned_type > - : public Quaternion<_Scalar> -{ - private: - template void _unaligned_copy(const Other& other) - { - // no resizing here, it's fixed-size anyway - ei_assign_impl::run(this->coeffs(), other.coeffs()); - } - public: - typedef Quaternion<_Scalar> aligned_base; - typedef typename aligned_base::Coefficients Coefficients; - ei_unaligned_type() : aligned_base(ei_constructor_without_unaligned_array_assert()) {} - ei_unaligned_type(const aligned_base& other) : aligned_base(ei_constructor_without_unaligned_array_assert()) - { - _unaligned_copy(other); - } - ei_unaligned_type(const ei_unaligned_type& other) : aligned_base(ei_constructor_without_unaligned_array_assert()) - { - _unaligned_copy(other); - } -}; - - -#endif // EIGEN_UNALIGNEDTYPE_H diff --git a/test/stdvector.cpp b/test/stdvector.cpp index 78e65e927..998945a6e 100644 --- a/test/stdvector.cpp +++ b/test/stdvector.cpp @@ -22,8 +22,8 @@ // License and a copy of the GNU General Public License along with // Eigen. If not, see . -#include "main.h" #include +#include "main.h" #include template