diff --git a/Eigen/Core b/Eigen/Core index 8189304d6..1ff197a28 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -1,30 +1,32 @@ #ifndef EIGEN_CORE_H #define EIGEN_CORE_H +// first thing Eigen does: prevent MSVC from committing suicide #ifdef _MSC_VER -#pragma warning( disable : 4181 4244 ) + #pragma warning( disable : 4181 4244 ) + #if (_MSC_VER >= 1500) // 2008 or later + // Remember that usage of defined() in a #define is undefined by the standard + #ifdef _M_IX86_FP + #if _M_IX86_FP >= 2 + #define EIGEN_SSE2_ON_MSVC_2008_OR_LATER + #endif + #endif + #endif #endif #ifdef __GNUC__ -#define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__>=x && __GNUC_MINOR__>=y) || __GNUC__>x) + #define EIGEN_GNUC_AT_LEAST(x,y) ((__GNUC__>=x && __GNUC_MINOR__>=y) || __GNUC__>x) #else -#define EIGEN_GNUC_AT_LEAST(x,y) 0 + #define EIGEN_GNUC_AT_LEAST(x,y) 0 +#endif + +// Remember that usage of defined() in a #define is undefined by the standard +#if (defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) ) + #define EIGEN_SSE2_BUT_NOT_OLD_GCC #endif #ifndef EIGEN_DONT_VECTORIZE - #define EIGEN_HAVE__SSE2__BUT_NOT_OLD_GCC ((defined __SSE2__) && ( (!defined __GNUC__) || EIGEN_GNUC_AT_LEAST(4,2) )) - - // Now check for SSE2 with MSVC. Normally we'd formulate this in 1 line using defined() but this triggers MSVC bugs. - #ifdef _M_IX86_FP - #if (_M_IX86_FP >= 2) - #define EIGEN_HAVE_MSVC_SSE2 1 - #endif - #endif - #ifndef EIGEN_HAVE_MSVC_SSE2 - #define EIGEN_HAVE_MSVC_SSE2 0 - #endif - - #if (EIGEN_HAVE__SSE2__BUT_NOT_OLD_GCC || EIGEN_HAVE_MSVC_SSE2) + #if defined (EIGEN_SSE2_BUT_NOT_OLD_GCC) || defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER) #define EIGEN_VECTORIZE #define EIGEN_VECTORIZE_SSE #include @@ -35,11 +37,11 @@ #ifdef __SSSE3__ #include #endif - #elif (defined __ALTIVEC__) + #elif defined __ALTIVEC__ #define EIGEN_VECTORIZE #define EIGEN_VECTORIZE_ALTIVEC #include - // We _need_ to #undef all these ugly tokens defined in + // We need to #undef all these ugly tokens defined in // => use __vector instead of vector #undef bool #undef vector @@ -56,8 +58,16 @@ #include #include -#if(defined(_MSC_VER) && defined(EIGEN_VECTORIZE)) -#include // for _aligned_malloc +#if defined(EIGEN_SSE2_ON_MSVC_2008_OR_LATER) && defined(EIGEN_VECTORIZE) + #include // for _aligned_malloc +#endif + +#if (defined(_CPPUNWIND) || defined(__EXCEPTIONS)) && !defined(EIGEN_NO_EXCEPTIONS) + #define EIGEN_EXCEPTIONS +#endif + +#ifdef EIGEN_EXCEPTIONS + #include #endif namespace Eigen { @@ -85,9 +95,9 @@ namespace Eigen { #include "src/Core/GenericPacketMath.h" #if defined EIGEN_VECTORIZE_SSE -#include "src/Core/arch/SSE/PacketMath.h" + #include "src/Core/arch/SSE/PacketMath.h" #elif defined EIGEN_VECTORIZE_ALTIVEC -#include "src/Core/arch/AltiVec/PacketMath.h" + #include "src/Core/arch/AltiVec/PacketMath.h" #endif #ifndef EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD @@ -97,10 +107,12 @@ namespace Eigen { #include "src/Core/Functors.h" #include "src/Core/MatrixBase.h" #include "src/Core/Coeffs.h" + #ifndef EIGEN_PARSED_BY_DOXYGEN // work around Doxygen bug triggered by Assign.h r814874 // at least confirmed with Doxygen 1.5.5 and 1.5.6 -#include "src/Core/Assign.h" + #include "src/Core/Assign.h" #endif + #include "src/Core/MatrixStorage.h" #include "src/Core/NestByValue.h" #include "src/Core/Flagged.h" diff --git a/Eigen/src/Core/util/Memory.h b/Eigen/src/Core/util/Memory.h index 209e273cd..63f9a07fc 100644 --- a/Eigen/src/Core/util/Memory.h +++ b/Eigen/src/Core/util/Memory.h @@ -26,12 +26,10 @@ #ifndef EIGEN_MEMORY_H #define EIGEN_MEMORY_H -#ifdef EIGEN_VECTORIZE -#ifndef _MSC_VER +#if defined(EIGEN_VECTORIZE) && !defined(_MSC_VER) // it seems we cannot assume posix_memalign is defined in the stdlib header extern "C" int posix_memalign (void **, size_t, size_t) throw (); #endif -#endif /** \internal * Static array automatically aligned if the total byte size is a multiple of 16 @@ -61,35 +59,47 @@ struct ei_byte_forcing_aligned_malloc { unsigned char c; // sizeof must be 1. }; - template struct ei_force_aligned_malloc { enum { ret = 0 }; }; template<> struct ei_force_aligned_malloc { enum { ret = 1 }; }; -/** \internal allocates \a size * sizeof(\a T) bytes with 16 bytes alignment. - * */ +/** \internal allocates \a size * sizeof(\a T) bytes. If vectorization is enabled and T is such that a packet + * containts more than one T, then the returned pointer is guaranteed to have 16 bytes alignment. + * On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown. + */ template inline T* ei_aligned_malloc(size_t size) { + T* result; + #ifdef EIGEN_VECTORIZE if(ei_packet_traits::size>1 || ei_force_aligned_malloc::ret) { #ifdef _MSC_VER - return static_cast(_aligned_malloc(size*sizeof(T), 16)); - #else - void* ptr; - if(posix_memalign(&ptr, 16, size*sizeof(T))==0) - return static_cast(ptr); - else - return 0; + result = static_cast(_aligned_malloc(size*sizeof(T), 16)); + #ifdef EIGEN_EXCEPTIONS + const int failed = (result == 0); + #endif + #else // not MSVC + #ifdef EIGEN_EXCEPTIONS + const int failed = + #endif + posix_memalign(reinterpret_cast(&result), 16, size*sizeof(T)); + #endif + + #ifdef EIGEN_EXCEPTIONS + if(failed) + throw std::bad_alloc(); #endif } else #endif - return new T[size]; // here we really want a new, not a malloc. Justification: if the user uses Eigen on + result = new T[size]; // here we really want a new, not a malloc. Justification: if the user uses Eigen on // some fancy scalar type such as multiple-precision numbers, and this type has a custom operator new, // then we want to honor this operator new! Anyway this type won't have vectorization so the vectorizing path // is irrelevant here. Yes, we should say somewhere in the docs that if the user uses a custom scalar type then // he can't have both vectorization and a custom operator new on his scalar type. + + return result; } /** \internal free memory allocated with ei_aligned_malloc */ diff --git a/test/main.h b/test/main.h index cfff229ca..73633687c 100644 --- a/test/main.h +++ b/test/main.h @@ -47,6 +47,8 @@ namespace Eigen #define EI_PP_CAT2(a,b) a ## b #define EI_PP_CAT(a,b) EI_PP_CAT2(a,b) +#define EIGEN_NO_EXCEPTIONS // disabling throwing assertions on bad alloc -- somehow makes the tests crawl + #ifndef EIGEN_NO_ASSERTION_CHECKING namespace Eigen