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
00173 inline void* aligned_malloc(size_t size)
00174 {
00175 #ifdef EIGEN_NO_MALLOC
00176 eigen_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
00177 #endif
00178
00179 void *result;
00180 #if !EIGEN_ALIGN
00181 result = std::malloc(size);
00182 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00183 result = std::malloc(size);
00184 #elif EIGEN_HAS_POSIX_MEMALIGN
00185 if(posix_memalign(&result, 16, size)) result = 0;
00186 #elif EIGEN_HAS_MM_MALLOC
00187 result = _mm_malloc(size, 16);
00188 #elif (defined _MSC_VER)
00189 result = _aligned_malloc(size, 16);
00190 #else
00191 result = handmade_aligned_malloc(size);
00192 #endif
00193
00194 #ifdef EIGEN_EXCEPTIONS
00195 if(result == 0)
00196 throw std::bad_alloc();
00197 #endif
00198 return result;
00199 }
00200
00202 inline void aligned_free(void *ptr)
00203 {
00204 #if !EIGEN_ALIGN
00205 std::free(ptr);
00206 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00207 std::free(ptr);
00208 #elif EIGEN_HAS_POSIX_MEMALIGN
00209 std::free(ptr);
00210 #elif EIGEN_HAS_MM_MALLOC
00211 _mm_free(ptr);
00212 #elif defined(_MSC_VER)
00213 _aligned_free(ptr);
00214 #else
00215 handmade_aligned_free(ptr);
00216 #endif
00217 }
00218
00224 inline void* aligned_realloc(void *ptr, size_t new_size, size_t old_size)
00225 {
00226 EIGEN_UNUSED_VARIABLE(old_size);
00227
00228 void *result;
00229 #if !EIGEN_ALIGN
00230 result = std::realloc(ptr,new_size);
00231 #elif EIGEN_MALLOC_ALREADY_ALIGNED
00232 result = std::realloc(ptr,new_size);
00233 #elif EIGEN_HAS_POSIX_MEMALIGN
00234 result = generic_aligned_realloc(ptr,new_size,old_size);
00235 #elif EIGEN_HAS_MM_MALLOC
00236
00237
00238
00239 #if defined(_MSC_VER) && defined(_mm_free)
00240 result = _aligned_realloc(ptr,new_size,16);
00241 #else
00242 result = generic_aligned_realloc(ptr,new_size,old_size);
00243 #endif
00244 #elif defined(_MSC_VER)
00245 result = _aligned_realloc(ptr,new_size,16);
00246 #else
00247 result = handmade_aligned_realloc(ptr,new_size,old_size);
00248 #endif
00249
00250 #ifdef EIGEN_EXCEPTIONS
00251 if (result==0 && new_size!=0)
00252 throw std::bad_alloc();
00253 #endif
00254 return result;
00255 }
00256
00257
00258
00259
00260
00264 template<bool Align> inline void* conditional_aligned_malloc(size_t size)
00265 {
00266 return aligned_malloc(size);
00267 }
00268
00269 template<> inline void* conditional_aligned_malloc<false>(size_t size)
00270 {
00271 #ifdef EIGEN_NO_MALLOC
00272 eigen_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
00273 #endif
00274
00275 void *result = std::malloc(size);
00276 #ifdef EIGEN_EXCEPTIONS
00277 if(!result) throw std::bad_alloc();
00278 #endif
00279 return result;
00280 }
00281
00283 template<bool Align> inline void conditional_aligned_free(void *ptr)
00284 {
00285 aligned_free(ptr);
00286 }
00287
00288 template<> inline void conditional_aligned_free<false>(void *ptr)
00289 {
00290 std::free(ptr);
00291 }
00292
00293 template<bool Align> inline void* conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
00294 {
00295 return aligned_realloc(ptr, new_size, old_size);
00296 }
00297
00298 template<> inline void* conditional_aligned_realloc<false>(void* ptr, size_t new_size, size_t)
00299 {
00300 return std::realloc(ptr, new_size);
00301 }
00302
00303
00304
00305
00306
00310 template<typename T> inline T* construct_elements_of_array(T *ptr, size_t size)
00311 {
00312 for (size_t i=0; i < size; ++i) ::new (ptr + i) T;
00313 return ptr;
00314 }
00315
00319 template<typename T> inline void destruct_elements_of_array(T *ptr, size_t size)
00320 {
00321
00322 if(ptr)
00323 while(size) ptr[--size].~T();
00324 }
00325
00326
00327
00328
00329
00334 template<typename T> inline T* aligned_new(size_t size)
00335 {
00336 T *result = reinterpret_cast<T*>(aligned_malloc(sizeof(T)*size));
00337 return construct_elements_of_array(result, size);
00338 }
00339
00340 template<typename T, bool Align> inline T* conditional_aligned_new(size_t size)
00341 {
00342 T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
00343 return construct_elements_of_array(result, size);
00344 }
00345
00349 template<typename T> inline void aligned_delete(T *ptr, size_t size)
00350 {
00351 destruct_elements_of_array<T>(ptr, size);
00352 aligned_free(ptr);
00353 }
00354
00358 template<typename T, bool Align> inline void conditional_aligned_delete(T *ptr, size_t size)
00359 {
00360 destruct_elements_of_array<T>(ptr, size);
00361 conditional_aligned_free<Align>(ptr);
00362 }
00363
00364 template<typename T, bool Align> inline T* conditional_aligned_realloc_new(T* pts, size_t new_size, size_t old_size)
00365 {
00366 if(new_size < old_size)
00367 destruct_elements_of_array(pts+new_size, old_size-new_size);
00368 T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
00369 if(new_size > old_size)
00370 construct_elements_of_array(result+old_size, new_size-old_size);
00371 return result;
00372 }
00373
00374
00375 template<typename T, bool Align> inline T* conditional_aligned_new_auto(size_t size)
00376 {
00377 T *result = reinterpret_cast<T*>(conditional_aligned_malloc<Align>(sizeof(T)*size));
00378 if(NumTraits<T>::RequireInitialization)
00379 construct_elements_of_array(result, size);
00380 return result;
00381 }
00382
00383 template<typename T, bool Align> inline T* conditional_aligned_realloc_new_auto(T* pts, size_t new_size, size_t old_size)
00384 {
00385 if(NumTraits<T>::RequireInitialization && (new_size < old_size))
00386 destruct_elements_of_array(pts+new_size, old_size-new_size);
00387 T *result = reinterpret_cast<T*>(conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
00388 if(NumTraits<T>::RequireInitialization && (new_size > old_size))
00389 construct_elements_of_array(result+old_size, new_size-old_size);
00390 return result;
00391 }
00392
00393 template<typename T, bool Align> inline void conditional_aligned_delete_auto(T *ptr, size_t size)
00394 {
00395 if(NumTraits<T>::RequireInitialization)
00396 destruct_elements_of_array<T>(ptr, size);
00397 conditional_aligned_free<Align>(ptr);
00398 }
00399
00400
00401
00418 template<typename Scalar, typename Index>
00419 inline static Index first_aligned(const Scalar* array, Index size)
00420 {
00421 typedef typename packet_traits<Scalar>::type Packet;
00422 enum { PacketSize = packet_traits<Scalar>::size,
00423 PacketAlignedMask = PacketSize-1
00424 };
00425
00426 if(PacketSize==1)
00427 {
00428
00429
00430 return 0;
00431 }
00432 else if(size_t(array) & (sizeof(Scalar)-1))
00433 {
00434
00435
00436 return size;
00437 }
00438 else
00439 {
00440 return std::min<Index>( (PacketSize - (Index((size_t(array)/sizeof(Scalar))) & PacketAlignedMask))
00441 & PacketAlignedMask, size);
00442 }
00443 }
00444
00445 }
00446
00447
00448
00449
00450
00463 #if (defined __linux__)
00464 #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
00465 ? alloca(SIZE) \
00466 : Eigen::internal::aligned_malloc(SIZE)
00467 #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) Eigen::internal::aligned_free(PTR)
00468 #elif defined(_MSC_VER)
00469 #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
00470 ? _alloca(SIZE) \
00471 : Eigen::internal::aligned_malloc(SIZE)
00472 #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) Eigen::internal::aligned_free(PTR)
00473 #else
00474 #define ei_aligned_stack_alloc(SIZE) Eigen::internal::aligned_malloc(SIZE)
00475 #define ei_aligned_stack_free(PTR,SIZE) Eigen::internal::aligned_free(PTR)
00476 #endif
00477
00478 #define ei_aligned_stack_new(TYPE,SIZE) Eigen::internal::construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE)
00479 #define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {Eigen::internal::destruct_elements_of_array<TYPE>(PTR, SIZE); \
00480 ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
00481
00482
00483
00484
00485
00486
00487 #if EIGEN_ALIGN
00488 #ifdef EIGEN_EXCEPTIONS
00489 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00490 void* operator new(size_t size, const std::nothrow_t&) throw() { \
00491 try { return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); } \
00492 catch (...) { return 0; } \
00493 return 0; \
00494 }
00495 #else
00496 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00497 void* operator new(size_t size, const std::nothrow_t&) throw() { \
00498 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00499 }
00500 #endif
00501
00502 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
00503 void *operator new(size_t size) { \
00504 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00505 } \
00506 void *operator new[](size_t size) { \
00507 return Eigen::internal::conditional_aligned_malloc<NeedsToAlign>(size); \
00508 } \
00509 void operator delete(void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
00510 void operator delete[](void * ptr) throw() { Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); } \
00511 \
00512 \
00513 \
00514 static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
00515 void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
00516 \
00517 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
00518 void operator delete(void *ptr, const std::nothrow_t&) throw() { \
00519 Eigen::internal::conditional_aligned_free<NeedsToAlign>(ptr); \
00520 } \
00521 typedef void eigen_aligned_operator_new_marker_type;
00522 #else
00523 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
00524 #endif
00525
00526 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
00527 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
00528 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
00529
00530
00531
00548 template<class T>
00549 class aligned_allocator
00550 {
00551 public:
00552 typedef size_t size_type;
00553 typedef std::ptrdiff_t difference_type;
00554 typedef T* pointer;
00555 typedef const T* const_pointer;
00556 typedef T& reference;
00557 typedef const T& const_reference;
00558 typedef T value_type;
00559
00560 template<class U>
00561 struct rebind
00562 {
00563 typedef aligned_allocator<U> other;
00564 };
00565
00566 pointer address( reference value ) const
00567 {
00568 return &value;
00569 }
00570
00571 const_pointer address( const_reference value ) const
00572 {
00573 return &value;
00574 }
00575
00576 aligned_allocator() throw()
00577 {
00578 }
00579
00580 aligned_allocator( const aligned_allocator& ) throw()
00581 {
00582 }
00583
00584 template<class U>
00585 aligned_allocator( const aligned_allocator<U>& ) throw()
00586 {
00587 }
00588
00589 ~aligned_allocator() throw()
00590 {
00591 }
00592
00593 size_type max_size() const throw()
00594 {
00595 return std::numeric_limits<size_type>::max();
00596 }
00597
00598 pointer allocate( size_type num, const_pointer* hint = 0 )
00599 {
00600 static_cast<void>( hint );
00601 return static_cast<pointer>( internal::aligned_malloc( num * sizeof(T) ) );
00602 }
00603
00604 void construct( pointer p, const T& value )
00605 {
00606 ::new( p ) T( value );
00607 }
00608
00609 void destroy( pointer p )
00610 {
00611 p->~T();
00612 }
00613
00614 void deallocate( pointer p, size_type )
00615 {
00616 internal::aligned_free( p );
00617 }
00618
00619 bool operator!=(const aligned_allocator<T>& ) const
00620 { return false; }
00621
00622 bool operator==(const aligned_allocator<T>& ) const
00623 { return true; }
00624 };
00625
00626
00627
00628 #if defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
00629 # if defined(__PIC__) && defined(__i386__)
00630
00631 # define EIGEN_CPUID(abcd,func,id) \
00632 __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));
00633 # else
00634
00635 # define EIGEN_CPUID(abcd,func,id) \
00636 __asm__ __volatile__ ("cpuid": "=a" (abcd[0]), "=b" (abcd[1]), "=c" (abcd[2]), "=d" (abcd[3]) : "a" (func), "c" (id) );
00637 # endif
00638 #elif defined(_MSC_VER)
00639 # if (_MSC_VER > 1500)
00640 # define EIGEN_CPUID(abcd,func,id) __cpuidex((int*)abcd,func,id)
00641 # endif
00642 #endif
00643
00644 namespace internal {
00645
00646 #ifdef EIGEN_CPUID
00647
00648 inline bool cpuid_is_vendor(int abcd[4], const char* vendor)
00649 {
00650 return abcd[1]==((int*)(vendor))[0] && abcd[3]==((int*)(vendor))[1] && abcd[2]==((int*)(vendor))[2];
00651 }
00652
00653 inline void queryCacheSizes_intel_direct(int& l1, int& l2, int& l3)
00654 {
00655 int abcd[4];
00656 l1 = l2 = l3 = 0;
00657 int cache_id = 0;
00658 int cache_type = 0;
00659 do {
00660 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00661 EIGEN_CPUID(abcd,0x4,cache_id);
00662 cache_type = (abcd[0] & 0x0F) >> 0;
00663 if(cache_type==1||cache_type==3)
00664 {
00665 int cache_level = (abcd[0] & 0xE0) >> 5;
00666 int ways = (abcd[1] & 0xFFC00000) >> 22;
00667 int partitions = (abcd[1] & 0x003FF000) >> 12;
00668 int line_size = (abcd[1] & 0x00000FFF) >> 0;
00669 int sets = (abcd[2]);
00670
00671 int cache_size = (ways+1) * (partitions+1) * (line_size+1) * (sets+1);
00672
00673 switch(cache_level)
00674 {
00675 case 1: l1 = cache_size; break;
00676 case 2: l2 = cache_size; break;
00677 case 3: l3 = cache_size; break;
00678 default: break;
00679 }
00680 }
00681 cache_id++;
00682 } while(cache_type>0 && cache_id<16);
00683 }
00684
00685 inline void queryCacheSizes_intel_codes(int& l1, int& l2, int& l3)
00686 {
00687 int abcd[4];
00688 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00689 l1 = l2 = l3 = 0;
00690 EIGEN_CPUID(abcd,0x00000002,0);
00691 unsigned char * bytes = reinterpret_cast<unsigned char *>(abcd)+2;
00692 bool check_for_p2_core2 = false;
00693 for(int i=0; i<14; ++i)
00694 {
00695 switch(bytes[i])
00696 {
00697 case 0x0A: l1 = 8; break;
00698 case 0x0C: l1 = 16; break;
00699 case 0x0E: l1 = 24; break;
00700 case 0x10: l1 = 16; break;
00701 case 0x15: l1 = 16; break;
00702 case 0x2C: l1 = 32; break;
00703 case 0x30: l1 = 32; break;
00704 case 0x60: l1 = 16; break;
00705 case 0x66: l1 = 8; break;
00706 case 0x67: l1 = 16; break;
00707 case 0x68: l1 = 32; break;
00708 case 0x1A: l2 = 96; break;
00709 case 0x22: l3 = 512; break;
00710 case 0x23: l3 = 1024; break;
00711 case 0x25: l3 = 2048; break;
00712 case 0x29: l3 = 4096; break;
00713 case 0x39: l2 = 128; break;
00714 case 0x3A: l2 = 192; break;
00715 case 0x3B: l2 = 128; break;
00716 case 0x3C: l2 = 256; break;
00717 case 0x3D: l2 = 384; break;
00718 case 0x3E: l2 = 512; break;
00719 case 0x40: l2 = 0; break;
00720 case 0x41: l2 = 128; break;
00721 case 0x42: l2 = 256; break;
00722 case 0x43: l2 = 512; break;
00723 case 0x44: l2 = 1024; break;
00724 case 0x45: l2 = 2048; break;
00725 case 0x46: l3 = 4096; break;
00726 case 0x47: l3 = 8192; break;
00727 case 0x48: l2 = 3072; break;
00728 case 0x49: if(l2!=0) l3 = 4096; else {check_for_p2_core2=true; l3 = l2 = 4096;} break;
00729 case 0x4A: l3 = 6144; break;
00730 case 0x4B: l3 = 8192; break;
00731 case 0x4C: l3 = 12288; break;
00732 case 0x4D: l3 = 16384; break;
00733 case 0x4E: l2 = 6144; break;
00734 case 0x78: l2 = 1024; break;
00735 case 0x79: l2 = 128; break;
00736 case 0x7A: l2 = 256; break;
00737 case 0x7B: l2 = 512; break;
00738 case 0x7C: l2 = 1024; break;
00739 case 0x7D: l2 = 2048; break;
00740 case 0x7E: l2 = 256; break;
00741 case 0x7F: l2 = 512; break;
00742 case 0x80: l2 = 512; break;
00743 case 0x81: l2 = 128; break;
00744 case 0x82: l2 = 256; break;
00745 case 0x83: l2 = 512; break;
00746 case 0x84: l2 = 1024; break;
00747 case 0x85: l2 = 2048; break;
00748 case 0x86: l2 = 512; break;
00749 case 0x87: l2 = 1024; break;
00750 case 0x88: l3 = 2048; break;
00751 case 0x89: l3 = 4096; break;
00752 case 0x8A: l3 = 8192; break;
00753 case 0x8D: l3 = 3072; break;
00754
00755 default: break;
00756 }
00757 }
00758 if(check_for_p2_core2 && l2 == l3)
00759 l3 = 0;
00760 l1 *= 1024;
00761 l2 *= 1024;
00762 l3 *= 1024;
00763 }
00764
00765 inline void queryCacheSizes_intel(int& l1, int& l2, int& l3, int max_std_funcs)
00766 {
00767 if(max_std_funcs>=4)
00768 queryCacheSizes_intel_direct(l1,l2,l3);
00769 else
00770 queryCacheSizes_intel_codes(l1,l2,l3);
00771 }
00772
00773 inline void queryCacheSizes_amd(int& l1, int& l2, int& l3)
00774 {
00775 int abcd[4];
00776 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00777 EIGEN_CPUID(abcd,0x80000005,0);
00778 l1 = (abcd[2] >> 24) * 1024;
00779 abcd[0] = abcd[1] = abcd[2] = abcd[3] = 0;
00780 EIGEN_CPUID(abcd,0x80000006,0);
00781 l2 = (abcd[2] >> 16) * 1024;
00782 l3 = ((abcd[3] & 0xFFFC000) >> 18) * 512 * 1024;
00783 }
00784 #endif
00785
00788 inline void queryCacheSizes(int& l1, int& l2, int& l3)
00789 {
00790 #ifdef EIGEN_CPUID
00791 int abcd[4];
00792
00793
00794 EIGEN_CPUID(abcd,0x0,0);
00795 int max_std_funcs = abcd[1];
00796 if(cpuid_is_vendor(abcd,"GenuineIntel"))
00797 queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
00798 else if(cpuid_is_vendor(abcd,"AuthenticAMD") || cpuid_is_vendor(abcd,"AMDisbetter!"))
00799 queryCacheSizes_amd(l1,l2,l3);
00800 else
00801
00802 queryCacheSizes_intel(l1,l2,l3,max_std_funcs);
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815 #else
00816 l1 = l2 = l3 = -1;
00817 #endif
00818 }
00819
00822 inline int queryL1CacheSize()
00823 {
00824 int l1(-1), l2, l3;
00825 queryCacheSizes(l1,l2,l3);
00826 return l1;
00827 }
00828
00831 inline int queryTopLevelCacheSize()
00832 {
00833 int l1, l2(-1), l3(-1);
00834 queryCacheSizes(l1,l2,l3);
00835 return std::max(l2,l3);
00836 }
00837
00838 }
00839
00840 #endif // EIGEN_MEMORY_H