mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
merge with default branch
This commit is contained in:
@@ -236,4 +236,22 @@ struct ei_blas_traits<Transpose<NestedXpr> >
|
||||
static inline Scalar extractScalarFactor(const XprType& x) { return Base::extractScalarFactor(x.nestedExpression()); }
|
||||
};
|
||||
|
||||
template<typename T, int Access=ei_blas_traits<T>::ActualAccess>
|
||||
struct ei_extract_data_selector {
|
||||
static const typename T::Scalar* run(const T& m)
|
||||
{
|
||||
return &ei_blas_traits<T>::extract(m).const_cast_derived().coeffRef(0,0); // FIXME this should be .data()
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ei_extract_data_selector<T,NoDirectAccess> {
|
||||
static typename T::Scalar* run(const T&) { return 0; }
|
||||
};
|
||||
|
||||
template<typename T> const typename T::Scalar* ei_extract_data(const T& m)
|
||||
{
|
||||
return ei_extract_data_selector<T>::run(m);
|
||||
}
|
||||
|
||||
#endif // EIGEN_BLASUTIL_H
|
||||
|
||||
@@ -86,11 +86,11 @@ const unsigned int EvalBeforeAssigningBit = 0x4;
|
||||
* Long version: means that the coefficients can be handled by packets
|
||||
* and start at a memory location whose alignment meets the requirements
|
||||
* of the present CPU architecture for optimized packet access. In the fixed-size
|
||||
* case, there is the additional condition that the total size of the coefficients
|
||||
* array is a multiple of the packet size, so that it is possible to access all the
|
||||
* coefficients by packets. In the dynamic-size case, there is no such condition
|
||||
* on the total size, so it might not be possible to access the few last coeffs
|
||||
* by packets.
|
||||
* case, there is the additional condition that it be possible to access all the
|
||||
* coefficients by packets (this implies the requirement that the size be a multiple of 16 bytes,
|
||||
* and that any nontrivial strides don't break the alignment). In the dynamic-size case,
|
||||
* there is no such condition on the total size and strides, so it might not be possible to access
|
||||
* all coeffs by packets.
|
||||
*
|
||||
* \note This bit can be set regardless of whether vectorization is actually enabled.
|
||||
* To check for actual vectorizability, see \a ActualPacketAccessBit.
|
||||
@@ -140,7 +140,7 @@ const unsigned int LinearAccessBit = 0x10;
|
||||
* Means that the underlying array of coefficients can be directly accessed. This means two things.
|
||||
* First, references to the coefficients must be available through coeffRef(int, int). This rules out read-only
|
||||
* expressions whose coefficients are computed on demand by coeff(int, int). Second, the memory layout of the
|
||||
* array of coefficients must be exactly the natural one suggested by rows(), cols(), stride(), and the RowMajorBit.
|
||||
* array of coefficients must be exactly the natural one suggested by rows(), cols(), outerStride(), innerStride(), and the RowMajorBit.
|
||||
* This rules out expressions such as Diagonal, whose coefficients, though referencable, do not have
|
||||
* such a regular memory layout.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2007-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -40,8 +41,10 @@ template<typename ExpressionType> class NestByValue;
|
||||
template<typename ExpressionType> class ForceAlignedAccess;
|
||||
template<typename ExpressionType> class SwapWrapper;
|
||||
template<typename MatrixType> class Minor;
|
||||
// MSVC will not compile when the expression ei_traits<MatrixType>::Flags&DirectAccessBit
|
||||
// is put into brackets like (ei_traits<MatrixType>::Flags&DirectAccessBit)!
|
||||
template<typename MatrixType, int BlockRows=Dynamic, int BlockCols=Dynamic,
|
||||
int _DirectAccessStatus = (ei_traits<MatrixType>::Flags&DirectAccessBit) ? HasDirectAccess : NoDirectAccess> class Block;
|
||||
int _DirectAccessStatus = ei_traits<MatrixType>::Flags&DirectAccessBit ? HasDirectAccess : NoDirectAccess> class Block;
|
||||
template<typename MatrixType, int Size=Dynamic> class VectorBlock;
|
||||
template<typename MatrixType> class Transpose;
|
||||
template<typename MatrixType> class Conjugate;
|
||||
@@ -60,7 +63,9 @@ template<typename _Scalar, int SizeAtCompileTime, int MaxSizeAtCompileTime=SizeA
|
||||
template<typename MatrixType, typename DiagonalType, int ProductOrder> class DiagonalProduct;
|
||||
template<typename MatrixType, int Index> class Diagonal;
|
||||
|
||||
template<typename MatrixType, int Options=Unaligned> class Map;
|
||||
template<int InnerStrideAtCompileTime, int OuterStrideAtCompileTime> class Stride;
|
||||
template<typename MatrixType, int Options=Unaligned, typename StrideType = Stride<0,0> > class Map;
|
||||
|
||||
template<typename Derived> class TriangularBase;
|
||||
template<typename MatrixType, unsigned int Mode> class TriangularView;
|
||||
template<typename MatrixType, unsigned int Mode> class SelfAdjointView;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
// 16 byte alignment is only useful for vectorization. Since it affects the ABI, we need to enable 16 byte alignment on all
|
||||
// platforms where vectorization might be enabled. In theory we could always enable alignment, but it can be a cause of problems
|
||||
// on some platforms, so we just disable it in certain common platform (compiler+architecture combinations) to avoid these problems.
|
||||
#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ppc__) || defined(__ia64__))
|
||||
#if defined(__GNUC__) && !(defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__ppc__) || defined(__ia64__) || defined(__ARM_NEON__))
|
||||
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 1
|
||||
#else
|
||||
#define EIGEN_GCC_AND_ARCH_DOESNT_WANT_ALIGNMENT 0
|
||||
@@ -78,30 +78,6 @@
|
||||
#define EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION ColMajor
|
||||
#endif
|
||||
|
||||
/** Defines the maximal loop size to enable meta unrolling of loops.
|
||||
* Note that the value here is expressed in Eigen's own notion of "number of FLOPS",
|
||||
* it does not correspond to the number of iterations or the number of instructions
|
||||
*/
|
||||
#ifndef EIGEN_UNROLLING_LIMIT
|
||||
#define EIGEN_UNROLLING_LIMIT 100
|
||||
#endif
|
||||
|
||||
/** Defines the maximal size in Bytes of blocks fitting in CPU cache.
|
||||
* The current value is set to generate blocks of 256x256 for float
|
||||
*
|
||||
* Typically for a single-threaded application you would set that to 25% of the size of your CPU caches in bytes
|
||||
*/
|
||||
#ifndef EIGEN_TUNE_FOR_CPU_CACHE_SIZE
|
||||
#define EIGEN_TUNE_FOR_CPU_CACHE_SIZE (sizeof(float)*256*256)
|
||||
#endif
|
||||
|
||||
/** Defines the maximal width of the blocks used in the triangular product and solver
|
||||
* for vectors (level 2 blas xTRMV and xTRSV). The default is 8.
|
||||
*/
|
||||
#ifndef EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH
|
||||
#define EIGEN_TUNE_TRIANGULAR_PANEL_WIDTH 8
|
||||
#endif
|
||||
|
||||
/** Allows to disable some optimizations which might affect the accuracy of the result.
|
||||
* Such optimization are enabled by default, and set EIGEN_FAST_MATH to 0 to disable them.
|
||||
* They currently include:
|
||||
@@ -211,7 +187,7 @@ using Eigen::ei_cos;
|
||||
*/
|
||||
#if !EIGEN_ALIGN
|
||||
#define EIGEN_ALIGN_TO_BOUNDARY(n)
|
||||
#elif (defined __GNUC__)
|
||||
#elif (defined __GNUC__) || (defined __PGI)
|
||||
#define EIGEN_ALIGN_TO_BOUNDARY(n) __attribute__((aligned(n)))
|
||||
#elif (defined _MSC_VER)
|
||||
#define EIGEN_ALIGN_TO_BOUNDARY(n) __declspec(align(n))
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2009 Kenneth Riddile <kfriddile@yahoo.com>
|
||||
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -24,26 +25,49 @@
|
||||
// License and a copy of the GNU General Public License along with
|
||||
// Eigen. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*** Platform checks for aligned malloc functions ***
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef EIGEN_MEMORY_H
|
||||
#define EIGEN_MEMORY_H
|
||||
|
||||
// FreeBSD 6 seems to have 16-byte aligned malloc
|
||||
// See http://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup
|
||||
// FreeBSD 7 seems to have 16-byte aligned malloc except on ARM and MIPS architectures
|
||||
// See http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup
|
||||
#if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
|
||||
#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
|
||||
// On 64-bit systems, glibc's malloc returns 16-byte-aligned pointers, see:
|
||||
// http://www.gnu.org/s/libc/manual/html_node/Aligned-Memory-Blocks.html
|
||||
// This is true at least since glibc 2.8.
|
||||
// This leaves the question how to detect 64-bit. According to this document,
|
||||
// http://gcc.fyxm.net/summit/2003/Porting%20to%2064%20bit.pdf
|
||||
// page 114, "[The] LP64 model [...] is used by all 64-bit UNIX ports" so it's indeed
|
||||
// quite safe, at least within the context of glibc, to equate 64-bit with LP64.
|
||||
#if defined(__GLIBC__) && ((__GLIBC__>=2 && __GLIBC_MINOR__ >= 8) || __GLIBC__>2) \
|
||||
&& defined(__LP64__)
|
||||
#define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 1
|
||||
#else
|
||||
#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
|
||||
#define EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED 0
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN64) || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
|
||||
// FreeBSD 6 seems to have 16-byte aligned malloc
|
||||
// See http://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup
|
||||
// FreeBSD 7 seems to have 16-byte aligned malloc except on ARM and MIPS architectures
|
||||
// See http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup
|
||||
#if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
|
||||
#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
|
||||
#else
|
||||
#define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) \
|
||||
|| defined(_WIN64) \
|
||||
|| EIGEN_GLIBC_MALLOC_ALREADY_ALIGNED \
|
||||
|| EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
|
||||
#define EIGEN_MALLOC_ALREADY_ALIGNED 1
|
||||
#else
|
||||
#define EIGEN_MALLOC_ALREADY_ALIGNED 0
|
||||
#endif
|
||||
|
||||
#if ((defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
|
||||
#if ((defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) \
|
||||
&& (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
|
||||
#define EIGEN_HAS_POSIX_MEMALIGN 1
|
||||
#else
|
||||
#define EIGEN_HAS_POSIX_MEMALIGN 0
|
||||
@@ -55,26 +79,90 @@
|
||||
#define EIGEN_HAS_MM_MALLOC 0
|
||||
#endif
|
||||
|
||||
/** \internal like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
|
||||
* Fast, but wastes 16 additional bytes of memory.
|
||||
* Does not throw any exception.
|
||||
/*****************************************************************************
|
||||
*** Implementation of handmade aligned functions ***
|
||||
*****************************************************************************/
|
||||
|
||||
/* ----- Hand made implementations of aligned malloc/free and realloc ----- */
|
||||
|
||||
/** \internal Like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
|
||||
* Fast, but wastes 16 additional bytes of memory. Does not throw any exception.
|
||||
*/
|
||||
inline void* ei_handmade_aligned_malloc(size_t size)
|
||||
{
|
||||
void *original = std::malloc(size+16);
|
||||
if (original == 0) return 0;
|
||||
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
|
||||
*(reinterpret_cast<void**>(aligned) - 1) = original;
|
||||
return aligned;
|
||||
}
|
||||
|
||||
/** \internal frees memory allocated with ei_handmade_aligned_malloc */
|
||||
/** \internal Frees memory allocated with ei_handmade_aligned_malloc */
|
||||
inline void ei_handmade_aligned_free(void *ptr)
|
||||
{
|
||||
if(ptr)
|
||||
std::free(*(reinterpret_cast<void**>(ptr) - 1));
|
||||
if (ptr) std::free(*(reinterpret_cast<void**>(ptr) - 1));
|
||||
}
|
||||
|
||||
/** \internal allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
|
||||
/** \internal
|
||||
* \brief Reallocates aligned memory.
|
||||
* Since we know that our handmade version is based on std::realloc
|
||||
* we can use std::realloc to implement efficient reallocation.
|
||||
*/
|
||||
inline void* ei_handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
|
||||
{
|
||||
if (ptr == 0) return ei_handmade_aligned_malloc(size);
|
||||
void *original = *(reinterpret_cast<void**>(ptr) - 1);
|
||||
original = std::realloc(original,size+16);
|
||||
if (original == 0) return 0;
|
||||
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
|
||||
*(reinterpret_cast<void**>(aligned) - 1) = original;
|
||||
return aligned;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*** Implementation of generic aligned realloc (when no realloc can be used)***
|
||||
*****************************************************************************/
|
||||
|
||||
void* ei_aligned_malloc(size_t size);
|
||||
void ei_aligned_free(void *ptr);
|
||||
|
||||
/** \internal
|
||||
* \brief Reallocates aligned memory.
|
||||
* Allows reallocation with aligned ptr types. This implementation will
|
||||
* always create a new memory chunk and copy the old data.
|
||||
*/
|
||||
inline void* ei_generic_aligned_realloc(void* ptr, size_t size, size_t old_size)
|
||||
{
|
||||
if (ptr==0)
|
||||
return ei_aligned_malloc(size);
|
||||
|
||||
if (size==0)
|
||||
{
|
||||
ei_aligned_free(ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* newptr = ei_aligned_malloc(size);
|
||||
if (newptr == 0)
|
||||
{
|
||||
errno = ENOMEM; // according to the standard
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ptr != 0)
|
||||
{
|
||||
std::memcpy(newptr, ptr, std::min(size,old_size));
|
||||
ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
return newptr;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*** Implementation of portable aligned versions of malloc/free/realloc ***
|
||||
*****************************************************************************/
|
||||
|
||||
/** \internal Allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
|
||||
* On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
*/
|
||||
inline void* ei_aligned_malloc(size_t size)
|
||||
@@ -85,9 +173,9 @@ inline void* ei_aligned_malloc(size_t size)
|
||||
|
||||
void *result;
|
||||
#if !EIGEN_ALIGN
|
||||
result = malloc(size);
|
||||
result = std::malloc(size);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
result = malloc(size);
|
||||
result = std::malloc(size);
|
||||
#elif EIGEN_HAS_POSIX_MEMALIGN
|
||||
if(posix_memalign(&result, 16, size)) result = 0;
|
||||
#elif EIGEN_HAS_MM_MALLOC
|
||||
@@ -105,7 +193,67 @@ inline void* ei_aligned_malloc(size_t size)
|
||||
return result;
|
||||
}
|
||||
|
||||
/** allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
|
||||
/** \internal Frees memory allocated with ei_aligned_malloc. */
|
||||
inline void ei_aligned_free(void *ptr)
|
||||
{
|
||||
#if !EIGEN_ALIGN
|
||||
std::free(ptr);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
std::free(ptr);
|
||||
#elif EIGEN_HAS_POSIX_MEMALIGN
|
||||
std::free(ptr);
|
||||
#elif EIGEN_HAS_MM_MALLOC
|
||||
_mm_free(ptr);
|
||||
#elif defined(_MSC_VER)
|
||||
_aligned_free(ptr);
|
||||
#else
|
||||
ei_handmade_aligned_free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* \brief Reallocates an aligned block of memory.
|
||||
* \throws std::bad_alloc if EIGEN_EXCEPTIONS are defined.
|
||||
**/
|
||||
inline void* ei_aligned_realloc(void *ptr, size_t new_size, size_t old_size)
|
||||
{
|
||||
(void)old_size; // Suppress 'unused variable' warning. Seen in boost tee.
|
||||
|
||||
void *result;
|
||||
#if !EIGEN_ALIGN
|
||||
result = std::realloc(ptr,new_size);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
result = std::realloc(ptr,new_size);
|
||||
#elif EIGEN_HAS_POSIX_MEMALIGN
|
||||
result = ei_generic_aligned_realloc(ptr,new_size,old_size);
|
||||
#elif EIGEN_HAS_MM_MALLOC
|
||||
// The defined(_mm_free) is just here to verify that this MSVC version
|
||||
// implements _mm_malloc/_mm_free based on the corresponding _aligned_
|
||||
// functions. This may not always be the case and we just try to be safe.
|
||||
#if defined(_MSC_VER) && defined(_mm_free)
|
||||
result = _aligned_realloc(ptr,new_size,16);
|
||||
#else
|
||||
result = ei_generic_aligned_realloc(ptr,new_size,old_size);
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
result = _aligned_realloc(ptr,new_size,16);
|
||||
#else
|
||||
result = ei_handmade_aligned_realloc(ptr,new_size,old_size);
|
||||
#endif
|
||||
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
if (result==0 && new_size!=0)
|
||||
throw std::bad_alloc();
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*** Implementation of conditionally aligned functions ***
|
||||
*****************************************************************************/
|
||||
|
||||
/** \internal Allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
|
||||
* On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
|
||||
*/
|
||||
template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
|
||||
@@ -126,7 +274,32 @@ template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \internal construct the elements of an array.
|
||||
/** \internal Frees memory allocated with ei_conditional_aligned_malloc */
|
||||
template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
|
||||
{
|
||||
ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
template<> inline void ei_conditional_aligned_free<false>(void *ptr)
|
||||
{
|
||||
std::free(ptr);
|
||||
}
|
||||
|
||||
template<bool Align> inline void* ei_conditional_aligned_realloc(void* ptr, size_t new_size, size_t old_size)
|
||||
{
|
||||
return ei_aligned_realloc(ptr, new_size, old_size);
|
||||
}
|
||||
|
||||
template<> inline void* ei_conditional_aligned_realloc<false>(void* ptr, size_t new_size, size_t)
|
||||
{
|
||||
return std::realloc(ptr, new_size);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*** Construction/destruction of array elements ***
|
||||
*****************************************************************************/
|
||||
|
||||
/** \internal Constructs the elements of an array.
|
||||
* The \a size parameter tells on how many objects to call the constructor of T.
|
||||
*/
|
||||
template<typename T> inline T* ei_construct_elements_of_array(T *ptr, size_t size)
|
||||
@@ -135,7 +308,20 @@ template<typename T> inline T* ei_construct_elements_of_array(T *ptr, size_t siz
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.
|
||||
/** \internal Destructs the elements of an array.
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T> inline void ei_destruct_elements_of_array(T *ptr, size_t size)
|
||||
{
|
||||
// always destruct an array starting from the end.
|
||||
while(size) ptr[--size].~T();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*** Implementation of aligned new/delete-like functions ***
|
||||
*****************************************************************************/
|
||||
|
||||
/** \internal Allocates \a size objects of type T. 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.
|
||||
* The default constructor of T is called.
|
||||
*/
|
||||
@@ -151,47 +337,7 @@ template<typename T, bool Align> inline T* ei_conditional_aligned_new(size_t siz
|
||||
return ei_construct_elements_of_array(result, size);
|
||||
}
|
||||
|
||||
/** \internal free memory allocated with ei_aligned_malloc
|
||||
*/
|
||||
inline void ei_aligned_free(void *ptr)
|
||||
{
|
||||
#if !EIGEN_ALIGN
|
||||
free(ptr);
|
||||
#elif EIGEN_MALLOC_ALREADY_ALIGNED
|
||||
free(ptr);
|
||||
#elif EIGEN_HAS_POSIX_MEMALIGN
|
||||
free(ptr);
|
||||
#elif EIGEN_HAS_MM_MALLOC
|
||||
_mm_free(ptr);
|
||||
#elif defined(_MSC_VER)
|
||||
_aligned_free(ptr);
|
||||
#else
|
||||
ei_handmade_aligned_free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \internal free memory allocated with ei_conditional_aligned_malloc
|
||||
*/
|
||||
template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
|
||||
{
|
||||
ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
template<> inline void ei_conditional_aligned_free<false>(void *ptr)
|
||||
{
|
||||
std::free(ptr);
|
||||
}
|
||||
|
||||
/** \internal destruct the elements of an array.
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T> inline void ei_destruct_elements_of_array(T *ptr, size_t size)
|
||||
{
|
||||
// always destruct an array starting from the end.
|
||||
while(size) ptr[--size].~T();
|
||||
}
|
||||
|
||||
/** \internal delete objects constructed with ei_aligned_new
|
||||
/** \internal Deletes objects constructed with ei_aligned_new
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
|
||||
@@ -200,7 +346,7 @@ template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
|
||||
ei_aligned_free(ptr);
|
||||
}
|
||||
|
||||
/** \internal delete objects constructed with ei_conditional_aligned_new
|
||||
/** \internal Deletes objects constructed with ei_conditional_aligned_new
|
||||
* The \a size parameters tells on how many objects to call the destructor of T.
|
||||
*/
|
||||
template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *ptr, size_t size)
|
||||
@@ -209,7 +355,17 @@ template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *pt
|
||||
ei_conditional_aligned_free<Align>(ptr);
|
||||
}
|
||||
|
||||
/** \internal \returns the index of the first element of the array that is well aligned for vectorization.
|
||||
template<typename T, bool Align> inline T* ei_conditional_aligned_realloc_new(T* pts, size_t new_size, size_t old_size)
|
||||
{
|
||||
T *result = reinterpret_cast<T*>(ei_conditional_aligned_realloc<Align>(reinterpret_cast<void*>(pts), sizeof(T)*new_size, sizeof(T)*old_size));
|
||||
if (new_size > old_size)
|
||||
ei_construct_elements_of_array(result+old_size, new_size-old_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/** \internal Returns the index of the first element of the array that is well aligned for vectorization.
|
||||
*
|
||||
* \param array the address of the start of the array
|
||||
* \param size the size of the array
|
||||
@@ -236,7 +392,7 @@ inline static Integer ei_first_aligned(const Scalar* array, Integer size)
|
||||
if(PacketSize==1)
|
||||
{
|
||||
// Either there is no vectorization, or a packet consists of exactly 1 scalar so that all elements
|
||||
// of the array have the same aligment.
|
||||
// of the array have the same alignment.
|
||||
return 0;
|
||||
}
|
||||
else if(size_t(array) & (sizeof(Scalar)-1))
|
||||
@@ -252,19 +408,23 @@ inline static Integer ei_first_aligned(const Scalar* array, Integer size)
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*** Implementation of runtime stack allocation (falling back to malloc) ***
|
||||
*****************************************************************************/
|
||||
|
||||
/** \internal
|
||||
* ei_aligned_stack_alloc(SIZE) allocates an aligned buffer of SIZE bytes
|
||||
* on the stack if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT, and
|
||||
* if stack allocation is supported by the platform (currently, this is linux only).
|
||||
* Otherwise the memory is allocated on the heap.
|
||||
* Data allocated with ei_aligned_stack_alloc \b must be freed by calling ei_aligned_stack_free(PTR,SIZE).
|
||||
* Allocates an aligned buffer of SIZE bytes on the stack if SIZE is smaller than
|
||||
* EIGEN_STACK_ALLOCATION_LIMIT, and if stack allocation is supported by the platform
|
||||
* (currently, this is Linux only). Otherwise the memory is allocated on the heap.
|
||||
* Data allocated with ei_aligned_stack_alloc \b must be freed by calling
|
||||
* ei_aligned_stack_free(PTR,SIZE).
|
||||
* \code
|
||||
* float * data = ei_aligned_stack_alloc(float,array.size());
|
||||
* // ...
|
||||
* ei_aligned_stack_free(data,float,array.size());
|
||||
* \endcode
|
||||
*/
|
||||
#ifdef __linux__
|
||||
#if (defined __linux__) && !(defined __ARM_NEON__)
|
||||
#define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
|
||||
? alloca(SIZE) \
|
||||
: ei_aligned_malloc(SIZE)
|
||||
@@ -279,6 +439,10 @@ inline static Integer ei_first_aligned(const Scalar* array, Integer size)
|
||||
ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*** Implementation of EIGEN_MAKE_ALIGNED_OPERATOR_NEW [_IF] ***
|
||||
*****************************************************************************/
|
||||
|
||||
#if EIGEN_ALIGN
|
||||
#ifdef EIGEN_EXCEPTIONS
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
|
||||
@@ -322,10 +486,11 @@ inline static Integer ei_first_aligned(const Scalar* array, Integer size)
|
||||
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/** \class aligned_allocator
|
||||
*
|
||||
* \brief stl compatible allocator to use with with 16 byte aligned types
|
||||
* \brief STL compatible allocator to use with with 16 byte aligned types
|
||||
*
|
||||
* Example:
|
||||
* \code
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// Eigen is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
@@ -46,7 +46,7 @@
|
||||
// if native static_assert is enabled, let's use it
|
||||
#define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
|
||||
|
||||
#else // CXX0X
|
||||
#else // not CXX0X
|
||||
|
||||
template<bool condition>
|
||||
struct ei_static_assert {};
|
||||
@@ -81,7 +81,8 @@
|
||||
BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER,
|
||||
THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX,
|
||||
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE,
|
||||
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES
|
||||
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_WITH_DIRECT_MEMORY_ACCESS_SUCH_AS_MAP_OR_PLAIN_MATRICES,
|
||||
YOU_ALREADY_SPECIFIED_THIS_STRIDE
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ template<int Value> class ei_int_if_dynamic
|
||||
{
|
||||
public:
|
||||
EIGEN_EMPTY_STRUCT_CTOR(ei_int_if_dynamic)
|
||||
explicit ei_int_if_dynamic(int) {}
|
||||
explicit ei_int_if_dynamic(int v) { EIGEN_ONLY_USED_FOR_DEBUG(v); ei_assert(v == Value); }
|
||||
static int value() { return Value; }
|
||||
void setValue(int) {}
|
||||
};
|
||||
@@ -58,7 +58,7 @@ template<int Value> class ei_int_if_dynamic
|
||||
template<> class ei_int_if_dynamic<Dynamic>
|
||||
{
|
||||
int m_value;
|
||||
ei_int_if_dynamic() {}
|
||||
ei_int_if_dynamic() { ei_assert(false); }
|
||||
public:
|
||||
explicit ei_int_if_dynamic(int value) : m_value(value) {}
|
||||
int value() const { return m_value; }
|
||||
@@ -87,12 +87,17 @@ class ei_compute_matrix_flags
|
||||
{
|
||||
enum {
|
||||
row_major_bit = Options&RowMajor ? RowMajorBit : 0,
|
||||
inner_max_size = MaxCols==1 ? MaxRows
|
||||
: MaxRows==1 ? MaxCols
|
||||
: row_major_bit ? MaxCols : MaxRows,
|
||||
is_big = inner_max_size == Dynamic,
|
||||
is_packet_size_multiple = MaxRows==Dynamic || MaxCols==Dynamic || ((MaxCols*MaxRows) % ei_packet_traits<Scalar>::size) == 0,
|
||||
aligned_bit = (((Options&DontAlign)==0) && (is_big || is_packet_size_multiple)) ? AlignedBit : 0,
|
||||
is_dynamic_size_storage = MaxRows==Dynamic || MaxCols==Dynamic,
|
||||
#if !defined(__ARM_NEON__)
|
||||
is_fixed_size_aligned
|
||||
= (!is_dynamic_size_storage) && (((MaxCols*MaxRows) % ei_packet_traits<Scalar>::size) == 0),
|
||||
#else
|
||||
// FIXME!!! This is a hack because ARM gcc does not honour __attribute__((aligned(16))) properly
|
||||
is_fixed_size_aligned = 0,
|
||||
#endif
|
||||
aligned_bit = (((Options&DontAlign)==0)
|
||||
&& (is_dynamic_size_storage || is_fixed_size_aligned))
|
||||
? AlignedBit : 0,
|
||||
packet_access_bit = ei_packet_traits<Scalar>::size > 1 && aligned_bit ? PacketAccessBit : 0
|
||||
};
|
||||
|
||||
@@ -214,7 +219,7 @@ struct ei_is_reference<T&>
|
||||
};
|
||||
|
||||
/**
|
||||
* The reference selector for template expressions. The idea is that we don't
|
||||
* \internal The reference selector for template expressions. The idea is that we don't
|
||||
* need to use references for expressions since they are light weight proxy
|
||||
* objects which should generate no copying overhead.
|
||||
**/
|
||||
|
||||
Reference in New Issue
Block a user