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
00028
00029
00030
00031
00032
00033
00034 #ifndef EIGEN_MEMORY_H
00035 #define EIGEN_MEMORY_H
00036
00037
00038
00039
00040
00041
00042
00043
00044 #if defined(__GLIBC__) && ((__GLIBC__>=2 && __GLIBC_MINOR__ >= 8) || __GLIBC__>2) \
00045 && defined(__LP64__)
00046 #define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 1
00047 #else
00048 #define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 0
00049 #endif
00050
00051
00052
00053
00054
00055 #if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
00056 #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
00057 #else
00058 #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
00059 #endif
00060
00061 #if defined(__APPLE__) \
00062 || defined(_WIN64) \
00063 || EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED \
00064 || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
00065 #define EIGEN_MALLOC_ALREADY_ALIGNED 1
00066 #else
00067 #define EIGEN_MALLOC_ALREADY_ALIGNED 0
00068 #endif
00069
00070 #if ((defined __QNXNTO__) || (defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) \
00071 && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
00072 #define EIGEN_HAS_POSIX_MEMALIGN 1
00073 #else
00074 #define EIGEN_HAS_POSIX_MEMALIGN 0
00075 #endif
00076
00077 #ifdef EIGEN_VECTORIZE_SSE
00078 #define EIGEN_HAS_MM_MALLOC 1
00079 #else
00080 #define EIGEN_HAS_MM_MALLOC 0
00081 #endif
00082
00083 namespace internal {
00084
00085
00086
00087
00088
00089
00090
00094 inline void* handmade_aligned_malloc(size_t size)
00095 {
00096 void *original = std::malloc(size+16);
00097 if (original == 0) return 0;
00098 void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
00099 *(reinterpret_cast<void**>(aligned) - 1) = original;
00100 return aligned;
00101 }
00102
00104 inline void handmade_aligned_free(void *ptr)
00105 {
00106 if (ptr) std::free(*(reinterpret_cast<void**>(ptr) - 1));
00107 }
00108
00114 inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
00115 {
00116 if (ptr == 0) return handmade_aligned_malloc(size);
00117 void *original = *(reinterpret_cast<void**>(ptr) - 1);
00118 original = std::realloc(original,size+16);
00119 if (original == 0) return 0;
00120 void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
00121 *(reinterpret_cast<void**>(aligned) - 1) = original;
00122 return aligned;
00123 }
00124
00125
00126
00127
00128
00129 void* aligned_malloc(size_t size);
00130 void aligned_free(void *ptr);
00131
00137 inline void* generic_aligned_realloc(void* ptr, size_t size, size_t old_size)
00138 {
00139 if (ptr==0)
00140 return aligned_malloc(size);
00141
00142 if (size==0)
00143 {
00144 aligned_free(ptr);
00145 return 0;
00146 }
00147
00148 void* newptr = aligned_malloc(size);
00149 if (newptr == 0)
00150 {
00151 #ifdef EIGEN_HAS_ERRNO
00152 errno = ENOMEM;
00153 #endif
00154 return 0;
00155 }
00156
00157 if (ptr != 0)
00158 {
00159 std::memcpy(newptr, ptr, (std::min)(size,old_size));
00160 aligned_free(ptr);
00161 }
00162
00163 return newptr;
00164 }
00165
00166
00167
00168
00169
00170 #ifdef EIGEN_NO_MALLOC
00171 inline void check_that_malloc_is_allowed()
00172 {
00173 eigen_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
00174 }
00175 #elif defined EIGEN_RUNTIME_NO_MALLOC
00176 inline bool is_malloc_allowed_impl(bool update, bool new_value = false)
00177 {
00178 static bool value = true;
00179 if (update == 1)
00180 value = new_value;
00181 return value;
00182 }
00183 inline bool is_malloc_allowed() { return is_malloc_allowed_impl(false); }
00184 inline bool set_is_malloc_allowed(bool new_value) { return is_malloc_allowed_impl(true, new_value); }
00185 inline void check_that_malloc_is_allowed()
00186 {
00187 eigen_assert(is_malloc_allowed() && "heap allocation is forbidden (EIGEN_RUNTIME_NO_MALLOC is defined and g_is_malloc_allowed is false)");
00188 }
00189 #else
00190 inline void check_that_malloc_is_allowed()
00191 {}
00192 #endif
00193
00197 inline void* aligned_malloc(size_t size)
00198 {
00199 check_that_malloc_is_allowed();
00200
00201 void *result;
00202 #if !EIGEN_ALIGN
00203 result = std::malloc(size);
00204 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00205 result = std::malloc(size);
00206 #elif EIGEN_HAS_POSIX_MEMALIGN
00207 if(posix_memalign(&result, 16, size)) result = 0;
00208 #elif EIGEN_HAS_MM_MALLOC
00209 result = _mm_malloc(size, 16);
00210 #elif (defined _MSC_VER)
00211 result = _aligned_malloc(size, 16);
00212 #else
00213 result = handmade_aligned_malloc(size);
00214 #endif
00215
00216 #ifdef EIGEN_EXCEPTIONS
00217 if(result == 0)
00218 throw std::bad_alloc();
00219 #endif
00220 return result;
00221 }
00222
00224 inline void aligned_free(void *ptr)
00225 {
00226 #if !EIGEN_ALIGN
00227 std::free(ptr);
00228 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00229 std::free(ptr);
00230 #elif EIGEN_HAS_POSIX_MEMALIGN
00231 std::free(ptr);
00232 #elif EIGEN_HAS_MM_MALLOC
00233 _mm_free(ptr);
00234 #elif defined(_MSC_VER)
00235 _aligned_free(ptr);
00236 #else
00237 handmade_aligned_free(ptr);
00238 #endif
00239 }
00240
00246 inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
00247 {
00248 EIGEN_UNUSED_VARIABLE(old_size);
00249
00250 void *result;
00251 #if !EIGEN_ALIGN
00252 result = std::realloc(ptr,new_size);
00253 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00254 result = std::realloc(ptr,new_size);
00255 #elif EIGEN_HAS_POSIX_MEMALIGN
00256 result = generic_aligned_realloc(ptr,new_size,old_size);
00257 #elif EIGEN_HAS_MM_MALLOC
00258
00259
00260
00261 #if defined(_MSC_VER) && defined(_mm_free)
00262 result = _aligned_realloc(ptr,new_size,16);
00263 #else
00264 result = generic_aligned_realloc(ptr,new_size,old_size);
00265 #endif
00266 #elif defined(_MSC_VER)
00267 result = _aligned_realloc(ptr,new_size,16);
00268 #else
00269 result = handmade_aligned_realloc(ptr,new_size,old_size);
00270 #endif
00271
00272 #ifdef EIGEN_EXCEPTIONS
00273 if (result==0 && new_size!=0)
00274 throw std::bad_alloc();
00275 #endif
00276 return result;
00277 }
00278
00279
00280
00281
00282
00286 template<bool Align> inline void* conditional_aligned_malloc(size_t size)
00287 {
00288 return aligned_malloc(size);
00289 }
00290
00291 template<> inline void* conditional_aligned_malloc<false>(size_t size)
00292 {
00293 check_that_malloc_is_allowed();
00294
00295 void *result = std::malloc(size);
00296 #ifdef EIGEN_EXCEPTIONS
00297 if(!result) throw std::bad_alloc();
00298 #endif
00299 return result;
00300 }
00301
00303 template<bool Align> inline void conditional_aligned_free(void *ptr)
00304 {
00305 aligned_free(ptr);
00306 }
00307
00308 template<> inline void conditional_aligned_free<false>(void *ptr)
00309 {
00310 std::free(ptr);
00311 }
00312
00313 template<bool Align> inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
00314 {
00315 return aligned_realloc(ptr, new_size, old_size);
00316 }
00317
00318 template<> inline void* conditional_aligned_realloc<false>(void* ptr, size_t new_size, size_t)
00319 {
00320 return std::realloc(ptr, new_size);
00321 }
00322
00323
00324
00325
00326
00330 template<typename T> inline T* construct_elements_of_array(T *ptr, size_t size)
00331 {
00332 for (size_t i=0; i < size; ++i) ::new (ptr + i) T;
00333 return ptr;
00334 }
00335
00339 template<typename T> inline void destruct_elements_of_array(T *ptr, size_t size)
00340 {
00341
00342 if(ptr)
00343 while(size) ptr[--size].~T();
00344 }
00345
00346
00347
00348
00349
00354 template<typename T> inline T* aligned_new(size_t size)
00355 {
00356 T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size));
00357 return construct_elements_of_array(result, size);
00358 }
00359
00360 template<typename T, bool Align> inline T* conditional_aligned_new(size_t size)
00361 {
00362 T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
00363 return construct_elements_of_array(result, size);
00364 }
00365
00369 template<typename T> inline void aligned_delete(T *ptr, size_t size)
00370 {
00371 destruct_elements_of_array<T>(ptr, size);
00372 aligned_free(ptr);
00373 }
00374
00378 template<typename T, bool Align> inline void conditional_aligned_delete(T *ptr, size_t size)
00379 {
00380 destruct_elements_of_array<T>(ptr, size);
00381 conditional_aligned_free<Align>(ptr);
00382 }
00383
00384 template<typename T, bool Align> inline T* conditional_aligned_realloc_new(T* pts, size_t new_size, size_t old_size)
00385 {
00386 if(new_size < old_size)
00387 destruct_elements_of_array(pts+new_size, old_size-new_size);
00388 T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
00389 if(new_size > old_size)
00390 construct_elements_of_array(result+old_size, new_size-old_size);
00391 return result;
00392 }
00393
00394
00395 template<typename T, bool Align> inline T* conditional_aligned_new_auto(size_t size)
00396 {
00397 T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
00398 if(NumTraits<T>::RequireInitialization)
00399 construct_elements_of_array(result, size);
00400 return result;
00401 }
00402
00403 template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(T* pts, size_t new_size, size_t old_size)
00404 {
00405 if(NumTraits<T>::RequireInitialization && (new_size < old_size))
00406 destruct_elements_of_array(pts+new_size, old_size-new_size);
00407 T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
00408 if(NumTraits<T>::RequireInitialization && (new_size > old_size))
00409 construct_elements_of_array(result+old_size, new_size-old_size);
00410 return result;
00411 }
00412
00413 template<typename T, bool Align> inline void conditional_aligned_delete_auto(T *ptr, size_t size)
00414 {
00415 if(NumTraits<T>::RequireInitialization)
00416 destruct_elements_of_array<T>(ptr, size);
00417 conditional_aligned_free<Align>(ptr);
00418 }
00419
00420
00421
00438 template<typename Scalar, typename Index>
00439 inline static Index first_aligned(const Scalar* array, Index size)
00440 {
00441 typedef typename packet_traits<Scalar>::type Packet;
00442 enum { PacketSize = packet_traits<Scalar>::size,
00443 PacketAlignedMask = PacketSize-1
00444 };
00445
00446 if(PacketSize==1)
00447 {
00448
00449
00450 return 0;
00451 }
00452 else if(size_t(array) & (sizeof(Scalar)-1))
00453 {
00454
00455
00456 return size;
00457 }
00458 else
00459 {
00460 return std::min<Index>( (PacketSize - (Index((size_t(array)/sizeof(Scalar))) & PacketAlignedMask))
00461 & PacketAlignedMask, size);
00462 }
00463 }
00464
00465 }
00466
00467
00468
00469
00470
00471
00472
00473 #ifndef EIGEN_ALLOCA
00474 #if (defined __linux__)
00475 #define EIGEN_ALLOCA alloca
00476 #elif defined(_MSC_VER)
00477 #define EIGEN_ALLOCA _alloca
00478 #endif
00479 #endif
00480
00481 namespace internal {
00482
00483
00484
00485 template<typename T> class aligned_stack_memory_handler
00486 {
00487 public:
00488
00489
00490
00491
00492
00493
00494 aligned_stack_memory_handler(T* ptr, size_t size, bool dealloc)
00495 : m_ptr(ptr), m_size(size), m_deallocate(dealloc)
00496 {
00497 if(NumTraits<T>::RequireInitialization && m_ptr)
00498 Eigen::internal::construct_elements_of_array(m_ptr, size);
00499 }
00500 ~aligned_stack_memory_handler()
00501 {
00502 if(NumTraits<T>::RequireInitialization && m_ptr)
00503 Eigen::internal::destruct_elements_of_array<T>(m_ptr, m_size);
00504 if(m_deallocate)
00505 Eigen::internal::aligned_free(m_ptr);
00506 }
00507 protected:
00508 T* m_ptr;
00509 size_t m_size;
00510 bool m_deallocate;
00511 };
00512
00513 }
00514
00530 #ifdef EIGEN_ALLOCA
00531
00532 #ifdef __arm__
00533 #define EIGEN_ALIGNED_ALLOCA(SIZE) reinterpret_cast<void*>((reinterpret_cast<size_t>(EIGEN_ALLOCA(SIZE+16)) & ~(size_t(15))) + 16)
00534 #else
00535 #define EIGEN_ALIGNED_ALLOCA EIGEN_ALLOCA
00536 #endif
00537
00538 #define ei_declare_aligned_stack_constructed_variable(TYPE,NAME,SIZE,BUFFER) \
00539 TYPE* NAME = (BUFFER)!=0 ? (BUFFER) \
00540 : reinterpret_cast<TYPE*>( \
00541 (sizeof(TYPE)*SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) ? EIGEN_ALIGNED_ALLOCA(sizeof(TYPE)*SIZE) \
00542 : Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE) ); \
00543 Eigen::internal::aligned_stack_memory_handler<TYPE> EIGEN_CAT(NAME,_stack_memory_destructor)((BUFFER)==0 ? NAME : 0,SIZE,sizeof(TYPE)*SIZE>EIGEN_STACK_ALLOCATION_LIMIT)
00544
00545 #else
00546
00547 #define ei_declare_aligned_stack_constructed_variable(TYPE,NAME,SIZE,BUFFER) \
00548 TYPE* NAME = (BUFFER)!=0 ? BUFFER : reinterpret_cast<TYPE*>(Eigen::internal::aligned_malloc(sizeof(TYPE)*SIZE)); \
00549 Eigen::internal::aligned_stack_memory_handler<TYPE> EIGEN_CAT(NAME,_stack_memory_destructor)((BUFFER)==0 ? NAME : 0,SIZE,true)
00550
00551 #endif
00552
00553
00554
00555
00556
00557
00558 #if EIGEN_ALIGN
00559 #ifdef EIGEN_EXCEPTIONS
00560 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00561 void* operator new(size_t size, const std::nothrow_t&) throw() { \
00562 try { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \
00563 catch (...) { return 0; } \
00564 return 0; \
00565 }
00566 #else
00567 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00568 void* operator new(size_t size, const std::nothrow_t&) throw() { \
00569 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00570 }
00571 #endif
00572
00573 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
00574 void *operator new(size_t size) { \
00575 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00576 } \
00577 void *operator new[](size_t size) { \
00578 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00579 } \
00580 void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
00581 void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
00582 \
00583 \
00584 \
00585 static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
00586 void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
00587 \
00588 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00589 void operator delete(void *ptr, const std::nothrow_t&) throw() { \
00590 Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); \
00591 } \
00592 typedef void eigen_aligned_operator_new_marker_type;
00593 #else
00594 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
00595 #endif
00596
00597 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
00598 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
00599 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
00600
00601
00602
00619 template<class T>
00620 class aligned_allocator
00621 {
00622 public:
00623 typedef size_t size_type;
00624 typedef std::ptrdiff_t difference_type;
00625 typedef T* pointer;
00626 typedef const T* const_pointer;
00627 typedef T& reference;
00628 typedef const T& const_reference;
00629 typedef T value_type;
00630
00631 template<class U>
00632 struct rebind
00633 {
00634 typedef aligned_allocator<U> other;
00635 };
00636
00637 pointer address( reference value ) const
00638 {
00639 return &value;
00640 }
00641
00642 const_pointer address( const_reference value ) const
00643 {
00644 return &value;
00645 }
00646
00647 aligned_allocator() throw()
00648 {
00649 }
00650
00651 aligned_allocator( const aligned_allocator& ) throw()
00652 {
00653 }
00654
00655 template<class U>
00656 aligned_allocator( const aligned_allocator<U>& ) throw()
00657 {
00658 }
00659
00660 ~aligned_allocator() throw()
00661 {
00662 }
00663
00664 size_type max_size() const throw()
00665 {
00666 return (std::numeric_limits<size_type>::max)();
00667 }
00668
00669 pointer allocate( size_type num, const void* hint = 0 )
00670 {
00671 EIGEN_UNUSED_VARIABLE(hint);
00672 return static_cast<pointer>( internal::aligned_malloc( num * sizeof(T) ) );
00673 }
00674
00675 void construct( pointer p, const T& value )
00676 {
00677 ::new( p ) T( value );
00678 }
00679
00680 void destroy( pointer p )
00681 {
00682 p->~T();
00683 }
00684
00685 void deallocate( pointer p, size_type )
00686 {
00687 internal::aligned_free( p );
00688 }
00689
00690 bool operator!=(const aligned_allocator<T>& ) const
00691 { return false; }
00692
00693 bool operator==(const aligned_allocator<T>& ) const
00694 { return true; }
00695 };
00696
00697
00698
00699 #if defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
00700 # if defined(__PIC__) && defined(__i386__)
00701
00702 # define EIGEN_CPUID(abcd,func,id) \
00703 __asm__ __volatile__ ("xchgl %%ebx, %%esi;cpuid; xchgl %%ebx,%%esi": "=a" (abcd[0]), "=S" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id));
00704 # else
00705
00706 # define EIGEN_CPUID(abcd,func,id) \
00707 __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id) );
00708 # endif
00709 #elif defined(_MSC_VER)
00710 # if (_MSC_VER > 1500)
00711 # define EIGEN_CPUID(abcd,func,id) __cpuidex((int*)abcd,func,id)
00712 # endif
00713 #endif
00714
00715 namespace internal {
00716
00717 #ifdef EIGEN_CPUID
00718
00719 inline bool cpuid_is_vendor(int abcd[4], const char* vendor)
00720 {
00721 return abcd[1]==((int*)(vendor))[0] && abcd[3]==((int*)(vendor))[1] && abcd[2]==((int*)(vendor))[2];
00722 }
00723
00724 inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3)
00725 {
00726 int abcd[4];
00727 l1 = l2 = l3 = 0;
00728 int cache_id = 0;
00729 int cache_type = 0;
00730 do {
00731 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00732 EIGEN_CPUID(abcd,0x4,cache_id);
00733 cache_type = (abcd[0] & 0x0F) >> 0;
00734 if(cache_type==1||cache_type==3)
00735 {
00736 int cache_level = (abcd[0] & 0xE0) >> 5;
00737 int ways = (abcd[1] & 0xFFC00000) >> 22;
00738 int partitions = (abcd[1] & 0x003FF000) >> 12;
00739 int line_size = (abcd[1] & 0x00000FFF) >> 0;
00740 int sets = (abcd[2]);
00741
00742 int cache_size = (ways+1) * (partitions+1) * (line_size+1) * (sets+1);
00743
00744 switch(cache_level)
00745 {
00746 case 1: l1 = cache_size; break;
00747 case 2: l2 = cache_size; break;
00748 case 3: l3 = cache_size; break;
00749 default: break;
00750 }
00751 }
00752 cache_id++;
00753 } while(cache_type>0 && cache_id<16);
00754 }
00755
00756 inline void queryCacheSizes_intel_codes(int& l1, int& l2, int& l3)
00757 {
00758 int abcd[4];
00759 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00760 l1 = l2 = l3 = 0;
00761 EIGEN_CPUID(abcd,0x00000002,0);
00762 unsigned char * bytes = reinterpret_cast<unsigned char *>(abcd)+2;
00763 bool check_for_p2_core2 = false;
00764 for(int i=0; i<14; ++i)
00765 {
00766 switch(bytes[i])
00767 {
00768 case 0x0A: l1 = 8; break;
00769 case 0x0C: l1 = 16; break;
00770 case 0x0E: l1 = 24; break;
00771 case 0x10: l1 = 16; break;
00772 case 0x15: l1 = 16; break;
00773 case 0x2C: l1 = 32; break;
00774 case 0x30: l1 = 32; break;
00775 case 0x60: l1 = 16; break;
00776 case 0x66: l1 = 8; break;
00777 case 0x67: l1 = 16; break;
00778 case 0x68: l1 = 32; break;
00779 case 0x1A: l2 = 96; break;
00780 case 0x22: l3 = 512; break;
00781 case 0x23: l3 = 1024; break;
00782 case 0x25: l3 = 2048; break;
00783 case 0x29: l3 = 4096; break;
00784 case 0x39: l2 = 128; break;
00785 case 0x3A: l2 = 192; break;
00786 case 0x3B: l2 = 128; break;
00787 case 0x3C: l2 = 256; break;
00788 case 0x3D: l2 = 384; break;
00789 case 0x3E: l2 = 512; break;
00790 case 0x40: l2 = 0; break;
00791 case 0x41: l2 = 128; break;
00792 case 0x42: l2 = 256; break;
00793 case 0x43: l2 = 512; break;
00794 case 0x44: l2 = 1024; break;
00795 case 0x45: l2 = 2048; break;
00796 case 0x46: l3 = 4096; break;
00797 case 0x47: l3 = 8192; break;
00798 case 0x48: l2 = 3072; break;
00799 case 0x49: if(l2!=0) l3 = 4096; else {check_for_p2_core2=true; l3 = l2 = 4096;} break;
00800 case 0x4A: l3 = 6144; break;
00801 case 0x4B: l3 = 8192; break;
00802 case 0x4C: l3 = 12288; break;
00803 case 0x4D: l3 = 16384; break;
00804 case 0x4E: l2 = 6144; break;
00805 case 0x78: l2 = 1024; break;
00806 case 0x79: l2 = 128; break;
00807 case 0x7A: l2 = 256; break;
00808 case 0x7B: l2 = 512; break;
00809 case 0x7C: l2 = 1024; break;
00810 case 0x7D: l2 = 2048; break;
00811 case 0x7E: l2 = 256; break;
00812 case 0x7F: l2 = 512; break;
00813 case 0x80: l2 = 512; break;
00814 case 0x81: l2 = 128; break;
00815 case 0x82: l2 = 256; break;
00816 case 0x83: l2 = 512; break;
00817 case 0x84: l2 = 1024; break;
00818 case 0x85: l2 = 2048; break;
00819 case 0x86: l2 = 512; break;
00820 case 0x87: l2 = 1024; break;
00821 case 0x88: l3 = 2048; break;
00822 case 0x89: l3 = 4096; break;
00823 case 0x8A: l3 = 8192; break;
00824 case 0x8D: l3 = 3072; break;
00825
00826 default: break;
00827 }
00828 }
00829 if(check_for_p2_core2 && l2 == l3)
00830 l3 = 0;
00831 l1 *= 1024;
00832 l2 *= 1024;
00833 l3 *= 1024;
00834 }
00835
00836 inline void queryCacheSizes_intel(int& l1, int& l2, int& l3, int max_std_funcs)
00837 {
00838 if(max_std_funcs>=4)
00839 queryCacheSizes_intel_direct(l1,l2,l3);
00840 else
00841 queryCacheSizes_intel_codes(l1,l2,l3);
00842 }
00843
00844 inline void queryCacheSizes_amd(int& l1, int& l2, int& l3)
00845 {
00846 int abcd[4];
00847 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00848 EIGEN_CPUID(abcd,0x80000005,0);
00849 l1 = (abcd[2] >> 24) * 1024;
00850 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00851 EIGEN_CPUID(abcd,0x80000006,0);
00852 l2 = (abcd[2] >> 16) * 1024;
00853 l3 = ((abcd[3] & 0xFFFC000) >> 18) * 512 * 1024;
00854 }
00855 #endif
00856
00859 inline void queryCacheSizes(int& l1, int& l2, int& l3)
00860 {
00861 #ifdef EIGEN_CPUID
00862 int abcd[4];
00863
00864
00865 EIGEN_CPUID(abcd,0x0,0);
00866 int max_std_funcs = abcd[1];
00867 if(cpuid_is_vendor(abcd,"GenuineIntel"))
00868 queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
00869 else if(cpuid_is_vendor(abcd,"AuthenticAMD") || cpuid_is_vendor(abcd,"AMDisbetter!"))
00870 queryCacheSizes_amd(l1,l2,l3);
00871 else
00872
00873 queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 #else
00887 l1 = l2 = l3 = -1;
00888 #endif
00889 }
00890
00893 inline int queryL1CacheSize()
00894 {
00895 int l1(-1), l2, l3;
00896 queryCacheSizes(l1,l2,l3);
00897 return l1;
00898 }
00899
00902 inline int queryTopLevelCacheSize()
00903 {
00904 int l1, l2(-1), l3(-1);
00905 queryCacheSizes(l1,l2,l3);
00906 return (std::max)(l2,l3);
00907 }
00908
00909 }
00910
00911 #endif // EIGEN_MEMORY_H