00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef EIGEN_MEMORY_H
00028 #define EIGEN_MEMORY_H
00029
00030
00031
00032
00033
00034 #if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
00035 #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
00036 #else
00037 #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
00038 #endif
00039
00040 #if defined(__APPLE__) || defined(_WIN64) || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
00041 #define EIGEN_MALLOC_ALREADY_ALIGNED 1
00042 #else
00043 #define EIGEN_MALLOC_ALREADY_ALIGNED 0
00044 #endif
00045
00046 #if (defined __QNXNTO__) || (((defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0))
00047 #define EIGEN_HAS_POSIX_MEMALIGN 1
00048 #else
00049 #define EIGEN_HAS_POSIX_MEMALIGN 0
00050 #endif
00051
00052 #ifdef EIGEN_VECTORIZE_SSE
00053 #define EIGEN_HAS_MM_MALLOC 1
00054 #else
00055 #define EIGEN_HAS_MM_MALLOC 0
00056 #endif
00057
00062 inline void* ei_handmade_aligned_malloc(std::size_t size)
00063 {
00064 void *original = std::malloc(size+16);
00065 void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::size_t(15))) + 16);
00066 *(reinterpret_cast<void**>(aligned) - 1) = original;
00067 return aligned;
00068 }
00069
00071 inline void ei_handmade_aligned_free(void *ptr)
00072 {
00073 if(ptr)
00074 std::free(*(reinterpret_cast<void**>(ptr) - 1));
00075 }
00076
00080 inline void* ei_aligned_malloc(std::size_t size)
00081 {
00082 #ifdef EIGEN_NO_MALLOC
00083 ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
00084 #endif
00085
00086 void *result;
00087 #if !EIGEN_ALIGN
00088 result = std::malloc(size);
00089 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00090 result = std::malloc(size);
00091 #elif EIGEN_HAS_POSIX_MEMALIGN
00092 if(posix_memalign(&result, 16, size)) result = 0;
00093 #elif EIGEN_HAS_MM_MALLOC
00094 result = _mm_malloc(size, 16);
00095 #elif (defined _MSC_VER)
00096 result = _aligned_malloc(size, 16);
00097 #else
00098 result = ei_handmade_aligned_malloc(size);
00099 #endif
00100
00101 #ifdef EIGEN_EXCEPTIONS
00102 if(result == 0)
00103 throw std::bad_alloc();
00104 #endif
00105 return result;
00106 }
00107
00111 template<bool Align> inline void* ei_conditional_aligned_malloc(std::size_t size)
00112 {
00113 return ei_aligned_malloc(size);
00114 }
00115
00116 template<> inline void* ei_conditional_aligned_malloc<false>(std::size_t size)
00117 {
00118 #ifdef EIGEN_NO_MALLOC
00119 ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
00120 #endif
00121
00122 void *result = std::malloc(size);
00123 #ifdef EIGEN_EXCEPTIONS
00124 if(!result) throw std::bad_alloc();
00125 #endif
00126 return result;
00127 }
00128
00132 template<typename T> inline T* ei_construct_elements_of_array(T *ptr, std::size_t size)
00133 {
00134 for (std::size_t i=0; i < size; ++i) ::new (ptr + i) T;
00135 return ptr;
00136 }
00137
00142 template<typename T> inline T* ei_aligned_new(std::size_t size)
00143 {
00144 T *result = reinterpret_cast<T*>(ei_aligned_malloc(sizeof(T)*size));
00145 return ei_construct_elements_of_array(result, size);
00146 }
00147
00148 template<typename T, bool Align> inline T* ei_conditional_aligned_new(std::size_t size)
00149 {
00150 T *result = reinterpret_cast<T*>(ei_conditional_aligned_malloc<Align>(sizeof(T)*size));
00151 return ei_construct_elements_of_array(result, size);
00152 }
00153
00156 inline void ei_aligned_free(void *ptr)
00157 {
00158 #if !EIGEN_ALIGN
00159 std::free(ptr);
00160 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00161 std::free(ptr);
00162 #elif EIGEN_HAS_POSIX_MEMALIGN
00163 std::free(ptr);
00164 #elif EIGEN_HAS_MM_MALLOC
00165 _mm_free(ptr);
00166 #elif defined(_MSC_VER)
00167 _aligned_free(ptr);
00168 #else
00169 ei_handmade_aligned_free(ptr);
00170 #endif
00171 }
00172
00175 template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
00176 {
00177 ei_aligned_free(ptr);
00178 }
00179
00180 template<> inline void ei_conditional_aligned_free<false>(void *ptr)
00181 {
00182 std::free(ptr);
00183 }
00184
00188 template<typename T> inline void ei_destruct_elements_of_array(T *ptr, std::size_t size)
00189 {
00190
00191 if(ptr)
00192 while(size) ptr[--size].~T();
00193 }
00194
00198 template<typename T> inline void ei_aligned_delete(T *ptr, std::size_t size)
00199 {
00200 ei_destruct_elements_of_array<T>(ptr, size);
00201 ei_aligned_free(ptr);
00202 }
00203
00207 template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *ptr, std::size_t size)
00208 {
00209 ei_destruct_elements_of_array<T>(ptr, size);
00210 ei_conditional_aligned_free<Align>(ptr);
00211 }
00212
00229 template<typename Scalar, typename Integer>
00230 inline static Integer ei_alignmentOffset(const Scalar* array, Integer size)
00231 {
00232 typedef typename ei_packet_traits<Scalar>::type Packet;
00233 enum { PacketSize = ei_packet_traits<Scalar>::size,
00234 PacketAlignedMask = PacketSize-1
00235 };
00236
00237 if(PacketSize==1)
00238 {
00239
00240
00241 return 0;
00242 }
00243 else if(std::size_t(array) & (sizeof(Scalar)-1))
00244 {
00245
00246
00247 return size;
00248 }
00249 else
00250 {
00251 return std::min<Integer>( (PacketSize - (Integer((std::size_t(array)/sizeof(Scalar))) & PacketAlignedMask))
00252 & PacketAlignedMask, size);
00253 }
00254 }
00255
00267 #ifdef __linux__
00268 #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
00269 ? alloca(SIZE) \
00270 : ei_aligned_malloc(SIZE)
00271 #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) ei_aligned_free(PTR)
00272 #else
00273 #define ei_aligned_stack_alloc(SIZE) ei_aligned_malloc(SIZE)
00274 #define ei_aligned_stack_free(PTR,SIZE) ei_aligned_free(PTR)
00275 #endif
00276
00277 #define ei_aligned_stack_new(TYPE,SIZE) ei_construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE)
00278 #define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_destruct_elements_of_array<TYPE>(PTR, SIZE); \
00279 ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
00280
00281
00282 #if EIGEN_ALIGN
00283 #ifdef EIGEN_EXCEPTIONS
00284 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00285 void* operator new(std::size_t size, const std::nothrow_t&) throw() { \
00286 try { return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); } \
00287 catch (...) { return 0; } \
00288 return 0; \
00289 }
00290 #else
00291 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00292 void* operator new(std::size_t size, const std::nothrow_t&) throw() { \
00293 return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
00294 }
00295 #endif
00296
00297 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
00298 void *operator new(std::size_t size) { \
00299 return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
00300 } \
00301 void *operator new[](std::size_t size) { \
00302 return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
00303 } \
00304 void operator delete(void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
00305 void operator delete[](void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
00306 \
00307 \
00308 \
00309 static void *operator new(std::size_t size, void *ptr) { return ::operator new(size,ptr); } \
00310 void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
00311 \
00312 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00313 void operator delete(void *ptr, const std::nothrow_t&) throw() { \
00314 Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); \
00315 } \
00316 typedef void ei_operator_new_marker_type;
00317 #else
00318 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
00319 #endif
00320
00321 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
00322 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
00323 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
00324
00325
00339 template<class T>
00340 class aligned_allocator
00341 {
00342 public:
00343 typedef std::size_t size_type;
00344 typedef std::ptrdiff_t difference_type;
00345 typedef T* pointer;
00346 typedef const T* const_pointer;
00347 typedef T& reference;
00348 typedef const T& const_reference;
00349 typedef T value_type;
00350
00351 template<class U>
00352 struct rebind
00353 {
00354 typedef aligned_allocator<U> other;
00355 };
00356
00357 pointer address( reference value ) const
00358 {
00359 return &value;
00360 }
00361
00362 const_pointer address( const_reference value ) const
00363 {
00364 return &value;
00365 }
00366
00367 aligned_allocator() throw()
00368 {
00369 }
00370
00371 aligned_allocator( const aligned_allocator& ) throw()
00372 {
00373 }
00374
00375 template<class U>
00376 aligned_allocator( const aligned_allocator<U>& ) throw()
00377 {
00378 }
00379
00380 ~aligned_allocator() throw()
00381 {
00382 }
00383
00384 size_type max_size() const throw()
00385 {
00386 return std::numeric_limits<size_type>::max();
00387 }
00388
00389 pointer allocate( size_type num, const void* hint = 0 )
00390 {
00391 static_cast<void>( hint );
00392 return static_cast<pointer>( ei_aligned_malloc( num * sizeof(T) ) );
00393 }
00394
00395 void construct( pointer p, const T& value )
00396 {
00397 ::new( p ) T( value );
00398 }
00399
00400 void destroy( pointer p )
00401 {
00402 p->~T();
00403 }
00404
00405 void deallocate( pointer p, size_type )
00406 {
00407 ei_aligned_free( p );
00408 }
00409
00410 bool operator!=(const aligned_allocator<T>& other) const
00411 { return false; }
00412
00413 bool operator==(const aligned_allocator<T>& other) const
00414 { return true; }
00415 };
00416
00417 #endif // EIGEN_MEMORY_H