Compare commits
	
		
			5 Commits
		
	
	
		
			aef926abf6
			...
			449ec69bab
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 449ec69bab | |||
|   | 3147391d94 | ||
|   | 115591b9e3 | ||
|   | fd100138dd | ||
|   | 1ec173b54e | 
| @ -86,7 +86,7 @@ MatrixBase<Derived>::dot(const MatrixBase<OtherDerived>& other) const | |||||||
| 
 | 
 | ||||||
| //---------- implementation of L2 norm and related functions ----------
 | //---------- implementation of L2 norm and related functions ----------
 | ||||||
| 
 | 
 | ||||||
| /** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the Frobenius norm.
 | /** \returns, for vectors, the squared \em l2 norm of \c *this, and for matrices the squared Frobenius norm.
 | ||||||
|   * In both cases, it consists in the sum of the square of all the matrix entries. |   * In both cases, it consists in the sum of the square of all the matrix entries. | ||||||
|   * For vectors, this is also equals to the dot product of \c *this with itself. |   * For vectors, this is also equals to the dot product of \c *this with itself. | ||||||
|   * |   * | ||||||
|  | |||||||
| @ -572,7 +572,9 @@ struct rint_retval | |||||||
| * Implementation of arg                                                     * | * Implementation of arg                                                     * | ||||||
| ****************************************************************************/ | ****************************************************************************/ | ||||||
| 
 | 
 | ||||||
| #if EIGEN_HAS_CXX11_MATH | // Visual Studio 2017 has a bug where arg(float) returns 0 for negative inputs.
 | ||||||
|  | // This seems to be fixed in VS 2019.
 | ||||||
|  | #if EIGEN_HAS_CXX11_MATH && (!EIGEN_COMP_MSVC || EIGEN_COMP_MSVC >= 1920) | ||||||
| // std::arg is only defined for types of std::complex, or integer types or float/double/long double
 | // std::arg is only defined for types of std::complex, or integer types or float/double/long double
 | ||||||
| template<typename Scalar, | template<typename Scalar, | ||||||
|           bool HasStdImpl = NumTraits<Scalar>::IsComplex || is_integral<Scalar>::value |           bool HasStdImpl = NumTraits<Scalar>::IsComplex || is_integral<Scalar>::value | ||||||
|  | |||||||
| @ -16,8 +16,8 @@ | |||||||
| //------------------------------------------------------------------------------------------
 | //------------------------------------------------------------------------------------------
 | ||||||
| 
 | 
 | ||||||
| #define EIGEN_WORLD_VERSION 3 | #define EIGEN_WORLD_VERSION 3 | ||||||
| #define EIGEN_MAJOR_VERSION 3 | #define EIGEN_MAJOR_VERSION 4 | ||||||
| #define EIGEN_MINOR_VERSION 91 | #define EIGEN_MINOR_VERSION 0 | ||||||
| 
 | 
 | ||||||
| #define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \ | #define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \ | ||||||
|                                       (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ |                                       (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ | ||||||
|  | |||||||
							
								
								
									
										145
									
								
								doc/examples/matrixfree.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								doc/examples/matrixfree.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,145 @@ | |||||||
|  | #include <iostream> | ||||||
|  | #include <Eigen/Core> | ||||||
|  | #include <Eigen/Dense> | ||||||
|  | #include <Eigen/IterativeLinearSolvers> | ||||||
|  | #include <unsupported/Eigen/IterativeSolvers> | ||||||
|  | 
 | ||||||
|  | class MatrixReplacement; | ||||||
|  | using Eigen::SparseMatrix; | ||||||
|  | 
 | ||||||
|  | namespace Eigen { | ||||||
|  | namespace internal { | ||||||
|  |   // MatrixReplacement looks-like a SparseMatrix, so let's inherits its traits:
 | ||||||
|  |   template<> | ||||||
|  |   struct traits<MatrixReplacement> :  public Eigen::internal::traits<Eigen::SparseMatrix<double> > | ||||||
|  |   {}; | ||||||
|  | } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Example of a matrix-free wrapper from a user type to Eigen's compatible type
 | ||||||
|  | // For the sake of simplicity, this example simply wrap a Eigen::SparseMatrix.
 | ||||||
|  | class MatrixReplacement : public Eigen::EigenBase<MatrixReplacement> { | ||||||
|  | public: | ||||||
|  |   // Required typedefs, constants, and method:
 | ||||||
|  |   typedef double Scalar; | ||||||
|  |   typedef double RealScalar; | ||||||
|  |   typedef int StorageIndex; | ||||||
|  |   enum { | ||||||
|  |     ColsAtCompileTime = Eigen::Dynamic, | ||||||
|  |     MaxColsAtCompileTime = Eigen::Dynamic, | ||||||
|  |     IsRowMajor = false | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   Index rows() const { return _n; } | ||||||
|  |   Index cols() const { return _n; } | ||||||
|  | 
 | ||||||
|  |   template<typename Rhs> | ||||||
|  |   Eigen::Product<MatrixReplacement,Rhs,Eigen::AliasFreeProduct> operator*(const Eigen::MatrixBase<Rhs>& x) const { | ||||||
|  |     return Eigen::Product<MatrixReplacement,Rhs,Eigen::AliasFreeProduct>(*this, x.derived()); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Custom API:
 | ||||||
|  |   MatrixReplacement(int n){ _n = n; } | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |   int _n; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Implementation of MatrixReplacement * Eigen::DenseVector though a specialization of internal::generic_product_impl:
 | ||||||
|  | namespace Eigen { | ||||||
|  | namespace internal { | ||||||
|  | 
 | ||||||
|  |   template<typename Rhs> | ||||||
|  |   struct generic_product_impl<MatrixReplacement, Rhs, SparseShape, DenseShape, GemvProduct> // GEMV stands for matrix-vector
 | ||||||
|  |   : generic_product_impl_base<MatrixReplacement,Rhs,generic_product_impl<MatrixReplacement,Rhs> > | ||||||
|  |   { | ||||||
|  |     typedef typename Product<MatrixReplacement,Rhs>::Scalar Scalar; | ||||||
|  | 
 | ||||||
|  |     template<typename Dest> | ||||||
|  |     static void scaleAndAddTo(Dest& dst, const MatrixReplacement& lhs, const Rhs& rhs, const Scalar& alpha) | ||||||
|  |     { | ||||||
|  |       // This method should implement "dst += alpha * lhs * rhs" inplace,
 | ||||||
|  |       // however, for iterative solvers, alpha is always equal to 1, so let's not bother about it.
 | ||||||
|  |       assert(alpha==Scalar(1) && "scaling is not implemented"); | ||||||
|  |       EIGEN_ONLY_USED_FOR_DEBUG(alpha); | ||||||
|  | 
 | ||||||
|  |       // LLS:
 | ||||||
|  |       // the matrix comes from 1D Poisson Eq. -u_{xx} = f
 | ||||||
|  |       // FD scheme is: 2 U_{i} - U_{i-1}-U_{i+1} = f_i, i=0,...,n-1
 | ||||||
|  |       // BC condition: U_{-1}=0, U_{n}=0
 | ||||||
|  |       int n = lhs.cols(); | ||||||
|  |       Scalar *dst_ptr = dst.data(); | ||||||
|  |       const Scalar *rhs_ptr = rhs.data(); | ||||||
|  | 
 | ||||||
|  |       for(int i=0;i<n;i++) { | ||||||
|  |         Scalar v=rhs_ptr[i]; | ||||||
|  |         Scalar vp,vm; | ||||||
|  |         if(i==n-1) { | ||||||
|  |           vp = 0.0; | ||||||
|  |         } else { | ||||||
|  |           vp = rhs_ptr[i+1]; | ||||||
|  |         } | ||||||
|  |         if(i==0) { | ||||||
|  |           vm = 0.0; | ||||||
|  |         } else { | ||||||
|  |           vm = rhs_ptr[i-1]; | ||||||
|  |         } | ||||||
|  |         dst_ptr[i]=2.0*v-vp-vm; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main() | ||||||
|  | { | ||||||
|  |   int n = 4; | ||||||
|  | 
 | ||||||
|  |   MatrixReplacement A(n); | ||||||
|  | 
 | ||||||
|  |   Eigen::VectorXd b(n), x; | ||||||
|  |   b.setOnes(); | ||||||
|  | 
 | ||||||
|  |   // Solve Ax = b using various iterative solver with matrix-free version:
 | ||||||
|  |   { | ||||||
|  |     Eigen::ConjugateGradient<MatrixReplacement, Eigen::Lower|Eigen::Upper, Eigen::IdentityPreconditioner> cg; | ||||||
|  |     cg.compute(A); | ||||||
|  |     x = cg.solve(b); | ||||||
|  |     std::cout << "CG:       #iterations: " << cg.iterations() << ", estimated error: " << cg.error() << std::endl; | ||||||
|  |     for(int i=0;i<n;i++) std::cout << "x["<<i<<"] = "<<x[i]<<"\n"; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   { | ||||||
|  |     Eigen::BiCGSTAB<MatrixReplacement, Eigen::IdentityPreconditioner> bicg; | ||||||
|  |     bicg.compute(A); | ||||||
|  |     x = bicg.solve(b); | ||||||
|  |     std::cout << "BiCGSTAB: #iterations: " << bicg.iterations() << ", estimated error: " << bicg.error() << std::endl; | ||||||
|  |     for(int i=0;i<n;i++) std::cout << "x["<<i<<"] = "<<x[i]<<"\n"; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   { | ||||||
|  |     Eigen::GMRES<MatrixReplacement, Eigen::IdentityPreconditioner> gmres; | ||||||
|  |     gmres.compute(A); | ||||||
|  |     x = gmres.solve(b); | ||||||
|  |     std::cout << "GMRES:    #iterations: " << gmres.iterations() << ", estimated error: " << gmres.error() << std::endl; | ||||||
|  |     for(int i=0;i<n;i++) std::cout << "x["<<i<<"] = "<<x[i]<<"\n"; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   { | ||||||
|  |     Eigen::DGMRES<MatrixReplacement, Eigen::IdentityPreconditioner> gmres; | ||||||
|  |     gmres.compute(A); | ||||||
|  |     x = gmres.solve(b); | ||||||
|  |     std::cout << "DGMRES:   #iterations: " << gmres.iterations() << ", estimated error: " << gmres.error() << std::endl; | ||||||
|  |     for(int i=0;i<n;i++) std::cout << "x["<<i<<"] = "<<x[i]<<"\n"; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   { | ||||||
|  |     Eigen::MINRES<MatrixReplacement, Eigen::Lower|Eigen::Upper, Eigen::IdentityPreconditioner> minres; | ||||||
|  |     minres.compute(A); | ||||||
|  |     x = minres.solve(b); | ||||||
|  |     std::cout << "MINRES:   #iterations: " << minres.iterations() << ", estimated error: " << minres.error() << std::endl; | ||||||
|  |     for(int i=0;i<n;i++) std::cout << "x["<<i<<"] = "<<x[i]<<"\n"; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -164,7 +164,6 @@ ei_add_test(nullary) | |||||||
| ei_add_test(mixingtypes) | ei_add_test(mixingtypes) | ||||||
| ei_add_test(io) | ei_add_test(io) | ||||||
| ei_add_test(packetmath "-DEIGEN_FAST_MATH=1") | ei_add_test(packetmath "-DEIGEN_FAST_MATH=1") | ||||||
| ei_add_test(unalignedassert) |  | ||||||
| ei_add_test(vectorization_logic) | ei_add_test(vectorization_logic) | ||||||
| ei_add_test(basicstuff) | ei_add_test(basicstuff) | ||||||
| ei_add_test(constructor) | ei_add_test(constructor) | ||||||
|  | |||||||
| @ -172,11 +172,6 @@ template<typename Scalar> void hyperplane_alignment() | |||||||
| 
 | 
 | ||||||
|   VERIFY_IS_APPROX(p1->coeffs(), p2->coeffs()); |   VERIFY_IS_APPROX(p1->coeffs(), p2->coeffs()); | ||||||
|   VERIFY_IS_APPROX(p1->coeffs(), p3->coeffs()); |   VERIFY_IS_APPROX(p1->coeffs(), p3->coeffs()); | ||||||
|    |  | ||||||
|   #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES > 0 |  | ||||||
|   if(internal::packet_traits<Scalar>::Vectorizable && internal::packet_traits<Scalar>::size<=4) |  | ||||||
|     VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Plane3a)); |  | ||||||
|   #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -110,11 +110,6 @@ template<typename Scalar> void parametrizedline_alignment() | |||||||
|   VERIFY_IS_APPROX(p1->origin(), p3->origin()); |   VERIFY_IS_APPROX(p1->origin(), p3->origin()); | ||||||
|   VERIFY_IS_APPROX(p1->direction(), p2->direction()); |   VERIFY_IS_APPROX(p1->direction(), p2->direction()); | ||||||
|   VERIFY_IS_APPROX(p1->direction(), p3->direction()); |   VERIFY_IS_APPROX(p1->direction(), p3->direction()); | ||||||
|    |  | ||||||
|   #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES>0 |  | ||||||
|   if(internal::packet_traits<Scalar>::Vectorizable && internal::packet_traits<Scalar>::size<=4) |  | ||||||
|     VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Line4a)); |  | ||||||
|   #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| EIGEN_DECLARE_TEST(geo_parametrizedline) | EIGEN_DECLARE_TEST(geo_parametrizedline) | ||||||
|  | |||||||
| @ -218,10 +218,6 @@ template<typename Scalar> void mapQuaternion(void){ | |||||||
|   VERIFY_IS_APPROX(q1.coeffs(), q2.coeffs()); |   VERIFY_IS_APPROX(q1.coeffs(), q2.coeffs()); | ||||||
|   VERIFY_IS_APPROX(q1.coeffs(), q3.coeffs()); |   VERIFY_IS_APPROX(q1.coeffs(), q3.coeffs()); | ||||||
|   VERIFY_IS_APPROX(q4.coeffs(), q3.coeffs()); |   VERIFY_IS_APPROX(q4.coeffs(), q3.coeffs()); | ||||||
|   #ifdef EIGEN_VECTORIZE |  | ||||||
|   if(internal::packet_traits<Scalar>::Vectorizable) |  | ||||||
|     VERIFY_RAISES_ASSERT((MQuaternionA(array3unaligned))); |  | ||||||
|   #endif |  | ||||||
|      |      | ||||||
|   VERIFY_IS_APPROX(mq1 * (mq1.inverse() * v1), v1); |   VERIFY_IS_APPROX(mq1 * (mq1.inverse() * v1), v1); | ||||||
|   VERIFY_IS_APPROX(mq1 * (mq1.conjugate() * v1), v1); |   VERIFY_IS_APPROX(mq1 * (mq1.conjugate() * v1), v1); | ||||||
| @ -281,10 +277,6 @@ template<typename Scalar> void quaternionAlignment(void){ | |||||||
| 
 | 
 | ||||||
|   VERIFY_IS_APPROX(q1->coeffs(), q2->coeffs()); |   VERIFY_IS_APPROX(q1->coeffs(), q2->coeffs()); | ||||||
|   VERIFY_IS_APPROX(q1->coeffs(), q3->coeffs()); |   VERIFY_IS_APPROX(q1->coeffs(), q3->coeffs()); | ||||||
|   #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES>0 |  | ||||||
|   if(internal::packet_traits<Scalar>::Vectorizable && internal::packet_traits<Scalar>::size<=4) |  | ||||||
|     VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(arrayunaligned)) QuaternionA)); |  | ||||||
|   #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&) | template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&) | ||||||
|  | |||||||
| @ -582,11 +582,6 @@ template<typename Scalar> void transform_alignment() | |||||||
|   VERIFY_IS_APPROX(p1->matrix(), p3->matrix()); |   VERIFY_IS_APPROX(p1->matrix(), p3->matrix()); | ||||||
|    |    | ||||||
|   VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3)); |   VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3)); | ||||||
|    |  | ||||||
|   #if defined(EIGEN_VECTORIZE) && EIGEN_MAX_STATIC_ALIGN_BYTES>0 |  | ||||||
|   if(internal::packet_traits<Scalar>::Vectorizable) |  | ||||||
|     VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Projective3a)); |  | ||||||
|   #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template<typename Scalar, int Dim, int Options> void transform_products() | template<typename Scalar, int Dim, int Options> void transform_products() | ||||||
|  | |||||||
| @ -1,180 +0,0 @@ | |||||||
| // This file is part of Eigen, a lightweight C++ template library
 |  | ||||||
| // for linear algebra.
 |  | ||||||
| //
 |  | ||||||
| // Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
 |  | ||||||
| // Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
 |  | ||||||
| //
 |  | ||||||
| // This Source Code Form is subject to the terms of the Mozilla
 |  | ||||||
| // Public License v. 2.0. If a copy of the MPL was not distributed
 |  | ||||||
| // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 |  | ||||||
| 
 |  | ||||||
| #if defined(EIGEN_TEST_PART_1) |  | ||||||
|   // default
 |  | ||||||
| #elif defined(EIGEN_TEST_PART_2) |  | ||||||
|   #define EIGEN_MAX_STATIC_ALIGN_BYTES 16 |  | ||||||
|   #define EIGEN_MAX_ALIGN_BYTES 16 |  | ||||||
| #elif defined(EIGEN_TEST_PART_3) |  | ||||||
|   #define EIGEN_MAX_STATIC_ALIGN_BYTES 32 |  | ||||||
|   #define EIGEN_MAX_ALIGN_BYTES 32 |  | ||||||
| #elif defined(EIGEN_TEST_PART_4) |  | ||||||
|   #define EIGEN_MAX_STATIC_ALIGN_BYTES 64 |  | ||||||
|   #define EIGEN_MAX_ALIGN_BYTES 64 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #include "main.h" |  | ||||||
| 
 |  | ||||||
| typedef Matrix<float,  6,1> Vector6f; |  | ||||||
| typedef Matrix<float,  8,1> Vector8f; |  | ||||||
| typedef Matrix<float, 12,1> Vector12f; |  | ||||||
| 
 |  | ||||||
| typedef Matrix<double, 5,1> Vector5d; |  | ||||||
| typedef Matrix<double, 6,1> Vector6d; |  | ||||||
| typedef Matrix<double, 7,1> Vector7d; |  | ||||||
| typedef Matrix<double, 8,1> Vector8d; |  | ||||||
| typedef Matrix<double, 9,1> Vector9d; |  | ||||||
| typedef Matrix<double,10,1> Vector10d; |  | ||||||
| typedef Matrix<double,12,1> Vector12d; |  | ||||||
| 
 |  | ||||||
| struct TestNew1 |  | ||||||
| { |  | ||||||
|   MatrixXd m; // good: m will allocate its own array, taking care of alignment.
 |  | ||||||
|   TestNew1() : m(20,20) {} |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct TestNew2 |  | ||||||
| { |  | ||||||
|   Matrix3d m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be 16-byte aligned,
 |  | ||||||
|               // 8-byte alignment is good enough here, which we'll get automatically
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct TestNew3 |  | ||||||
| { |  | ||||||
|   Vector2f m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be 16-byte aligned
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct TestNew4 |  | ||||||
| { |  | ||||||
|   EIGEN_MAKE_ALIGNED_OPERATOR_NEW |  | ||||||
|   Vector2d m; |  | ||||||
|   float f; // make the struct have sizeof%16!=0 to make it a little more tricky when we allow an array of 2 such objects
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct TestNew5 |  | ||||||
| { |  | ||||||
|   EIGEN_MAKE_ALIGNED_OPERATOR_NEW |  | ||||||
|   float f; // try the f at first -- the EIGEN_ALIGN_MAX attribute of m should make that still work
 |  | ||||||
|   Matrix4f m; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct TestNew6 |  | ||||||
| { |  | ||||||
|   Matrix<float,2,2,DontAlign> m; // good: no alignment requested
 |  | ||||||
|   float f; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template<bool Align> struct Depends |  | ||||||
| { |  | ||||||
|   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(Align) |  | ||||||
|   Vector2d m; |  | ||||||
|   float f; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template<typename T> |  | ||||||
| void check_unalignedassert_good() |  | ||||||
| { |  | ||||||
|   T *x, *y; |  | ||||||
|   x = new T; |  | ||||||
|   delete x; |  | ||||||
|   y = new T[2]; |  | ||||||
|   delete[] y; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #if EIGEN_MAX_STATIC_ALIGN_BYTES>0 |  | ||||||
| template<typename T> |  | ||||||
| void construct_at_boundary(int boundary) |  | ||||||
| { |  | ||||||
|   char buf[sizeof(T)+256]; |  | ||||||
|   size_t _buf = reinterpret_cast<internal::UIntPtr>(buf); |  | ||||||
|   _buf += (EIGEN_MAX_ALIGN_BYTES - (_buf % EIGEN_MAX_ALIGN_BYTES)); // make 16/32/...-byte aligned
 |  | ||||||
|   _buf += boundary; // make exact boundary-aligned
 |  | ||||||
|   T *x = ::new(reinterpret_cast<void*>(_buf)) T; |  | ||||||
|   x[0].setZero(); // just in order to silence warnings
 |  | ||||||
|   x->~T(); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| void unalignedassert() |  | ||||||
| { |  | ||||||
| #if EIGEN_MAX_STATIC_ALIGN_BYTES>0 |  | ||||||
|   construct_at_boundary<Vector2f>(4); |  | ||||||
|   construct_at_boundary<Vector3f>(4); |  | ||||||
|   construct_at_boundary<Vector4f>(16); |  | ||||||
|   construct_at_boundary<Vector6f>(4); |  | ||||||
|   construct_at_boundary<Vector8f>(EIGEN_MAX_ALIGN_BYTES); |  | ||||||
|   construct_at_boundary<Vector12f>(16); |  | ||||||
|   construct_at_boundary<Matrix2f>(16); |  | ||||||
|   construct_at_boundary<Matrix3f>(4); |  | ||||||
|   construct_at_boundary<Matrix4f>(EIGEN_MAX_ALIGN_BYTES); |  | ||||||
| 
 |  | ||||||
|   construct_at_boundary<Vector2d>(16); |  | ||||||
|   construct_at_boundary<Vector3d>(4); |  | ||||||
|   construct_at_boundary<Vector4d>(EIGEN_MAX_ALIGN_BYTES); |  | ||||||
|   construct_at_boundary<Vector5d>(4); |  | ||||||
|   construct_at_boundary<Vector6d>(16); |  | ||||||
|   construct_at_boundary<Vector7d>(4); |  | ||||||
|   construct_at_boundary<Vector8d>(EIGEN_MAX_ALIGN_BYTES); |  | ||||||
|   construct_at_boundary<Vector9d>(4); |  | ||||||
|   construct_at_boundary<Vector10d>(16); |  | ||||||
|   construct_at_boundary<Vector12d>(EIGEN_MAX_ALIGN_BYTES); |  | ||||||
|   construct_at_boundary<Matrix2d>(EIGEN_MAX_ALIGN_BYTES); |  | ||||||
|   construct_at_boundary<Matrix3d>(4); |  | ||||||
|   construct_at_boundary<Matrix4d>(EIGEN_MAX_ALIGN_BYTES); |  | ||||||
| 
 |  | ||||||
|   construct_at_boundary<Vector2cf>(16); |  | ||||||
|   construct_at_boundary<Vector3cf>(4); |  | ||||||
|   construct_at_boundary<Vector2cd>(EIGEN_MAX_ALIGN_BYTES); |  | ||||||
|   construct_at_boundary<Vector3cd>(16); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|   check_unalignedassert_good<TestNew1>(); |  | ||||||
|   check_unalignedassert_good<TestNew2>(); |  | ||||||
|   check_unalignedassert_good<TestNew3>(); |  | ||||||
| 
 |  | ||||||
|   check_unalignedassert_good<TestNew4>(); |  | ||||||
|   check_unalignedassert_good<TestNew5>(); |  | ||||||
|   check_unalignedassert_good<TestNew6>(); |  | ||||||
|   check_unalignedassert_good<Depends<true> >(); |  | ||||||
| 
 |  | ||||||
| #if EIGEN_MAX_STATIC_ALIGN_BYTES>0 |  | ||||||
|   if(EIGEN_MAX_ALIGN_BYTES>=16) |  | ||||||
|   { |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4f>(8)); |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8f>(8)); |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector12f>(8)); |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2d>(8)); |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4d>(8)); |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector6d>(8)); |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8d>(8)); |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector10d>(8)); |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector12d>(8)); |  | ||||||
|     // Complexes are disabled because the compiler might aggressively vectorize
 |  | ||||||
|     // the initialization of complex coeffs to 0 before we can check for alignedness
 |  | ||||||
|     //VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cf>(8));
 |  | ||||||
|     VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4i>(8)); |  | ||||||
|   } |  | ||||||
|   for(int b=8; b<EIGEN_MAX_ALIGN_BYTES; b+=8) |  | ||||||
|   { |  | ||||||
|     if(b<32)  VERIFY_RAISES_ASSERT(construct_at_boundary<Vector8f>(b)); |  | ||||||
|     if(b<64)  VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4f>(b)); |  | ||||||
|     if(b<32)  VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4d>(b)); |  | ||||||
|     if(b<32)  VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix2d>(b)); |  | ||||||
|     if(b<128) VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4d>(b)); |  | ||||||
|     //if(b<32)  VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cd>(b));
 |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| EIGEN_DECLARE_TEST(unalignedassert) |  | ||||||
| { |  | ||||||
|   CALL_SUBTEST(unalignedassert()); |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user