* fix ei_handmade_aligned_realloc (was calling realloc on wrong ptr)

* add missing std::  (at least for QNX compatibility)
* add big comments to "structure" the file
This commit is contained in:
Benoit Jacob 2010-02-28 09:10:41 -05:00
parent ff8c2149c1
commit a480e7e60f

View File

@ -25,6 +25,11 @@
// License and a copy of the GNU General Public License along with // License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>. // Eigen. If not, see <http://www.gnu.org/licenses/>.
/*****************************************************************************
*** Platform checks for aligned malloc functions ***
*****************************************************************************/
#ifndef EIGEN_MEMORY_H #ifndef EIGEN_MEMORY_H
#define EIGEN_MEMORY_H #define EIGEN_MEMORY_H
@ -56,11 +61,9 @@
#define EIGEN_HAS_MM_MALLOC 0 #define EIGEN_HAS_MM_MALLOC 0
#endif #endif
/*****************************************************************************
// Forward declarations required for the implementation *** Implementation of handmade aligned functions ***
// of ei_handmade_aligned_realloc. *****************************************************************************/
void* ei_aligned_malloc(size_t size);
void ei_aligned_free(void *ptr);
/* ----- Hand made implementations of aligned malloc/free and realloc ----- */ /* ----- Hand made implementations of aligned malloc/free and realloc ----- */
@ -87,17 +90,24 @@ inline void ei_handmade_aligned_free(void *ptr)
* Since we know that our handmade version is based on std::realloc * Since we know that our handmade version is based on std::realloc
* we can use std::realloc to implement efficient reallocation. * we can use std::realloc to implement efficient reallocation.
*/ */
inline void* ei_handmade_aligned_realloc(void* ptr, size_t size, size_t) inline void* ei_handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
{ {
if (ptr == 0) return ei_handmade_aligned_malloc(size); if (ptr == 0) return ei_handmade_aligned_malloc(size);
void *original = *(reinterpret_cast<void**>(ptr) - 1); void *original = *(reinterpret_cast<void**>(ptr) - 1);
original = std::realloc(ptr,size+16); original = std::realloc(original,size+16);
if (original == 0) return 0; if (original == 0) return 0;
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16); void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
*(reinterpret_cast<void**>(aligned) - 1) = original; *(reinterpret_cast<void**>(aligned) - 1) = original;
return aligned; 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 /** \internal
* \brief Reallocates aligned memory. * \brief Reallocates aligned memory.
* Allows reallocation with aligned ptr types. This implementation will * Allows reallocation with aligned ptr types. This implementation will
@ -130,7 +140,9 @@ inline void* ei_generic_aligned_realloc(void* ptr, size_t size, size_t old_size)
return newptr; return newptr;
} }
/* --- Eigen internal implementations of aligned malloc/free and realloc --- */ /*****************************************************************************
*** Implementation of portable aligned versions of malloc/free/realloc ***
*****************************************************************************/
/** \internal Allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment. /** \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. * On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
@ -143,9 +155,9 @@ inline void* ei_aligned_malloc(size_t size)
void *result; void *result;
#if !EIGEN_ALIGN #if !EIGEN_ALIGN
result = malloc(size); result = std::malloc(size);
#elif EIGEN_MALLOC_ALREADY_ALIGNED #elif EIGEN_MALLOC_ALREADY_ALIGNED
result = malloc(size); result = std::malloc(size);
#elif EIGEN_HAS_POSIX_MEMALIGN #elif EIGEN_HAS_POSIX_MEMALIGN
if(posix_memalign(&result, 16, size)) result = 0; if(posix_memalign(&result, 16, size)) result = 0;
#elif EIGEN_HAS_MM_MALLOC #elif EIGEN_HAS_MM_MALLOC
@ -201,11 +213,11 @@ inline void* ei_aligned_realloc(void *ptr, size_t new_size, size_t old_size)
// The defined(_mm_free) is just here to verify that this MSVC version // The defined(_mm_free) is just here to verify that this MSVC version
// implements _mm_malloc/_mm_free based on the corresponding _aligned_ // 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. // functions. This may not always be the case and we just try to be safe.
#if defined(_MSC_VER) && defined(_mm_free) #if defined(_MSC_VER) && defined(_mm_free)
result = _aligned_realloc(ptr,new_size,16); result = _aligned_realloc(ptr,new_size,16);
#else #else
result = ei_generic_aligned_realloc(ptr,new_size,old_size); result = ei_generic_aligned_realloc(ptr,new_size,old_size);
#endif #endif
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
result = _aligned_realloc(ptr,new_size,16); result = _aligned_realloc(ptr,new_size,16);
#else #else
@ -219,7 +231,9 @@ inline void* ei_aligned_realloc(void *ptr, size_t new_size, size_t old_size)
return result; return result;
} }
/* ---- Conditional implementations of aligned malloc/free and realloc ---- */ /*****************************************************************************
*** Implementation of conditionally aligned functions ***
*****************************************************************************/
/** \internal Allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned. /** \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. * On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
@ -263,7 +277,9 @@ template<> inline void* ei_conditional_aligned_realloc<false>(void* ptr, size_t
return std::realloc(ptr, new_size); return std::realloc(ptr, new_size);
} }
/* ---------- Eigen internal memory management of array elements --------- */ /*****************************************************************************
*** Construction/destruction of array elements ***
*****************************************************************************/
/** \internal Constructs the elements of an array. /** \internal Constructs the elements of an array.
* The \a size parameter tells on how many objects to call the constructor of T. * The \a size parameter tells on how many objects to call the constructor of T.
@ -283,7 +299,9 @@ template<typename T> inline void ei_destruct_elements_of_array(T *ptr, size_t si
while(size) ptr[--size].~T(); while(size) ptr[--size].~T();
} }
/* -- Memory management of arrays (allocation & in-place creation of elements) -- */ /*****************************************************************************
*** 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. /** \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. * On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
@ -327,6 +345,7 @@ template<typename T, bool Align> inline T* ei_conditional_aligned_realloc_new(T*
return result; return result;
} }
/****************************************************************************/
/** \internal Returns the index of the first element of the array that is well aligned for vectorization. /** \internal Returns the index of the first element of the array that is well aligned for vectorization.
* *
@ -371,6 +390,10 @@ inline static Integer ei_first_aligned(const Scalar* array, Integer size)
} }
} }
/*****************************************************************************
*** Implementation of runtime stack allocation (falling back to malloc) ***
*****************************************************************************/
/** \internal /** \internal
* Allocates an aligned buffer of SIZE bytes on the stack if SIZE is smaller than * 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 * EIGEN_STACK_ALLOCATION_LIMIT, and if stack allocation is supported by the platform
@ -398,6 +421,10 @@ inline static Integer ei_first_aligned(const Scalar* array, Integer size)
ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0) ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
/*****************************************************************************
*** Implementation of EIGEN_MAKE_ALIGNED_OPERATOR_NEW [_IF] ***
*****************************************************************************/
#if EIGEN_ALIGN #if EIGEN_ALIGN
#ifdef EIGEN_EXCEPTIONS #ifdef EIGEN_EXCEPTIONS
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \ #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
@ -441,6 +468,7 @@ inline static Integer ei_first_aligned(const Scalar* array, Integer size)
#define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,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)) EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
/****************************************************************************/
/** \class aligned_allocator /** \class aligned_allocator
* *