didnt mean to commit to Eigen2 since its externally maintained.
[blender-staging.git] / extern / Eigen2 / Eigen / src / Core / util / Memory.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
5 // Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6 // Copyright (C) 2009 Kenneth Riddile <kfriddile@yahoo.com>
7 //
8 // Eigen is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 3 of the License, or (at your option) any later version.
12 //
13 // Alternatively, you can redistribute it and/or
14 // modify it under the terms of the GNU General Public License as
15 // published by the Free Software Foundation; either version 2 of
16 // the License, or (at your option) any later version.
17 //
18 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public
24 // License and a copy of the GNU General Public License along with
25 // Eigen. If not, see <http://www.gnu.org/licenses/>.
26
27 #ifndef EIGEN_MEMORY_H
28 #define EIGEN_MEMORY_H
29
30 // FreeBSD 6 seems to have 16-byte aligned malloc
31 // See http://svn.freebsd.org/viewvc/base/stable/6/lib/libc/stdlib/malloc.c?view=markup
32 // FreeBSD 7 seems to have 16-byte aligned malloc except on ARM and MIPS architectures
33 // See http://svn.freebsd.org/viewvc/base/stable/7/lib/libc/stdlib/malloc.c?view=markup
34 #if defined(__FreeBSD__) && !defined(__arm__) && !defined(__mips__)
35 #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 1
36 #else
37 #define EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED 0
38 #endif
39
40 #if defined(__APPLE__) || defined(_WIN64) || EIGEN_FREEBSD_MALLOC_ALREADY_ALIGNED
41   #define EIGEN_MALLOC_ALREADY_ALIGNED 1
42 #else
43   #define EIGEN_MALLOC_ALREADY_ALIGNED 0
44 #endif
45
46 #if ((defined _GNU_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600))) && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
47   #define EIGEN_HAS_POSIX_MEMALIGN 1
48 #else
49   #define EIGEN_HAS_POSIX_MEMALIGN 0
50 #endif
51
52 #ifdef EIGEN_VECTORIZE_SSE
53   #define EIGEN_HAS_MM_MALLOC 1
54 #else
55   #define EIGEN_HAS_MM_MALLOC 0
56 #endif
57
58 /** \internal like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
59   * Fast, but wastes 16 additional bytes of memory.
60   * Does not throw any exception.
61   */
62 inline void* ei_handmade_aligned_malloc(size_t size)
63 {
64   void *original = malloc(size+16);
65   void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16);
66   *(reinterpret_cast<void**>(aligned) - 1) = original;
67   return aligned;
68 }
69
70 /** \internal frees memory allocated with ei_handmade_aligned_malloc */
71 inline void ei_handmade_aligned_free(void *ptr)
72 {
73   if(ptr)
74     free(*(reinterpret_cast<void**>(ptr) - 1));
75 }
76
77 /** \internal allocates \a size bytes. The returned pointer is guaranteed to have 16 bytes alignment.
78   * On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
79   */
80 inline void* ei_aligned_malloc(size_t size)
81 {
82   #ifdef EIGEN_NO_MALLOC
83     ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
84   #endif
85
86   void *result;  
87   #if !EIGEN_ALIGN
88     result = malloc(size);
89   #elif EIGEN_MALLOC_ALREADY_ALIGNED
90     result = malloc(size);
91   #elif EIGEN_HAS_POSIX_MEMALIGN
92     if(posix_memalign(&result, 16, size)) result = 0;
93   #elif EIGEN_HAS_MM_MALLOC
94     result = _mm_malloc(size, 16);
95   #elif (defined _MSC_VER)
96     result = _aligned_malloc(size, 16);
97   #else
98     result = ei_handmade_aligned_malloc(size);
99   #endif
100     
101   #ifdef EIGEN_EXCEPTIONS
102     if(result == 0)
103       throw std::bad_alloc();
104   #endif
105   return result;
106 }
107
108 /** allocates \a size bytes. If Align is true, then the returned ptr is 16-byte-aligned.
109   * On allocation error, the returned pointer is null, and if exceptions are enabled then a std::bad_alloc is thrown.
110   */
111 template<bool Align> inline void* ei_conditional_aligned_malloc(size_t size)
112 {
113   return ei_aligned_malloc(size);
114 }
115
116 template<> inline void* ei_conditional_aligned_malloc<false>(size_t size)
117 {
118   #ifdef EIGEN_NO_MALLOC
119     ei_assert(false && "heap allocation is forbidden (EIGEN_NO_MALLOC is defined)");
120   #endif
121
122   void *result = malloc(size);
123   #ifdef EIGEN_EXCEPTIONS
124     if(!result) throw std::bad_alloc();
125   #endif
126   return result;
127 }
128
129 /** \internal construct the elements of an array.
130   * The \a size parameter tells on how many objects to call the constructor of T.
131   */
132 template<typename T> inline T* ei_construct_elements_of_array(T *ptr, size_t size)
133 {
134   for (size_t i=0; i < size; ++i) ::new (ptr + i) T;
135   return ptr;
136 }
137
138 /** allocates \a size objects of type T. The returned pointer is guaranteed to have 16 bytes alignment.
139   * On allocation error, the returned pointer is undefined, but if exceptions are enabled then a std::bad_alloc is thrown.
140   * The default constructor of T is called.
141   */
142 template<typename T> inline T* ei_aligned_new(size_t size)
143 {
144   T *result = reinterpret_cast<T*>(ei_aligned_malloc(sizeof(T)*size));
145   return ei_construct_elements_of_array(result, size);
146 }
147
148 template<typename T, bool Align> inline T* ei_conditional_aligned_new(size_t size)
149 {
150   T *result = reinterpret_cast<T*>(ei_conditional_aligned_malloc<Align>(sizeof(T)*size));
151   return ei_construct_elements_of_array(result, size);
152 }
153
154 /** \internal free memory allocated with ei_aligned_malloc
155   */
156 inline void ei_aligned_free(void *ptr)
157 {
158   #if !EIGEN_ALIGN
159     free(ptr);
160   #elif EIGEN_MALLOC_ALREADY_ALIGNED
161     free(ptr);
162   #elif EIGEN_HAS_POSIX_MEMALIGN
163     free(ptr);
164   #elif EIGEN_HAS_MM_MALLOC
165     _mm_free(ptr);
166   #elif defined(_MSC_VER)
167     _aligned_free(ptr);
168   #else
169     ei_handmade_aligned_free(ptr);
170   #endif
171 }
172
173 /** \internal free memory allocated with ei_conditional_aligned_malloc
174   */
175 template<bool Align> inline void ei_conditional_aligned_free(void *ptr)
176 {
177   ei_aligned_free(ptr);
178 }
179
180 template<> inline void ei_conditional_aligned_free<false>(void *ptr)
181 {
182   free(ptr);
183 }
184
185 /** \internal destruct the elements of an array.
186   * The \a size parameters tells on how many objects to call the destructor of T.
187   */
188 template<typename T> inline void ei_destruct_elements_of_array(T *ptr, size_t size)
189 {
190   // always destruct an array starting from the end.
191   while(size) ptr[--size].~T();
192 }
193
194 /** \internal delete objects constructed with ei_aligned_new
195   * The \a size parameters tells on how many objects to call the destructor of T.
196   */
197 template<typename T> inline void ei_aligned_delete(T *ptr, size_t size)
198 {
199   ei_destruct_elements_of_array<T>(ptr, size);
200   ei_aligned_free(ptr);
201 }
202
203 /** \internal delete objects constructed with ei_conditional_aligned_new
204   * The \a size parameters tells on how many objects to call the destructor of T.
205   */
206 template<typename T, bool Align> inline void ei_conditional_aligned_delete(T *ptr, size_t size)
207 {
208   ei_destruct_elements_of_array<T>(ptr, size);
209   ei_conditional_aligned_free<Align>(ptr);
210 }
211
212 /** \internal \returns the number of elements which have to be skipped such that data are 16 bytes aligned */
213 template<typename Scalar>
214 inline static int ei_alignmentOffset(const Scalar* ptr, int maxOffset)
215 {
216   typedef typename ei_packet_traits<Scalar>::type Packet;
217   const int PacketSize = ei_packet_traits<Scalar>::size;
218   const int PacketAlignedMask = PacketSize-1;
219   const bool Vectorized = PacketSize>1;
220   return Vectorized
221           ? std::min<int>( (PacketSize - (int((size_t(ptr)/sizeof(Scalar))) & PacketAlignedMask))
222                            & PacketAlignedMask, maxOffset)
223           : 0;
224 }
225
226 /** \internal
227   * ei_aligned_stack_alloc(SIZE) allocates an aligned buffer of SIZE bytes
228   * on the stack if SIZE is smaller than EIGEN_STACK_ALLOCATION_LIMIT.
229   * Otherwise the memory is allocated on the heap.
230   * Data allocated with ei_aligned_stack_alloc \b must be freed by calling ei_aligned_stack_free(PTR,SIZE).
231   * \code
232   * float * data = ei_aligned_stack_alloc(float,array.size());
233   * // ...
234   * ei_aligned_stack_free(data,float,array.size());
235   * \endcode
236   */
237 #ifdef __linux__
238   #define ei_aligned_stack_alloc(SIZE) (SIZE<=EIGEN_STACK_ALLOCATION_LIMIT) \
239                                     ? alloca(SIZE) \
240                                     : ei_aligned_malloc(SIZE)
241   #define ei_aligned_stack_free(PTR,SIZE) if(SIZE>EIGEN_STACK_ALLOCATION_LIMIT) ei_aligned_free(PTR)
242 #else
243   #define ei_aligned_stack_alloc(SIZE) ei_aligned_malloc(SIZE)
244   #define ei_aligned_stack_free(PTR,SIZE) ei_aligned_free(PTR)
245 #endif
246
247 #define ei_aligned_stack_new(TYPE,SIZE) ei_construct_elements_of_array(reinterpret_cast<TYPE*>(ei_aligned_stack_alloc(sizeof(TYPE)*SIZE)), SIZE)
248 #define ei_aligned_stack_delete(TYPE,PTR,SIZE) do {ei_destruct_elements_of_array<TYPE>(PTR, SIZE); \
249                                                    ei_aligned_stack_free(PTR,sizeof(TYPE)*SIZE);} while(0)
250
251
252 #if EIGEN_ALIGN
253   #ifdef EIGEN_EXCEPTIONS
254     #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
255       void* operator new(size_t size, const std::nothrow_t&) throw() { \
256         try { return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); } \
257         catch (...) { return 0; } \
258         return 0; \
259       }
260   #else
261     #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
262       void* operator new(size_t size, const std::nothrow_t&) throw() { \
263         return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
264       }
265   #endif
266
267   #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign) \
268       void *operator new(size_t size) { \
269         return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
270       } \
271       void *operator new[](size_t size) { \
272         return Eigen::ei_conditional_aligned_malloc<NeedsToAlign>(size); \
273       } \
274       void operator delete(void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
275       void operator delete[](void * ptr) throw() { Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); } \
276       /* in-place new and delete. since (at least afaik) there is no actual   */ \
277       /* memory allocated we can safely let the default implementation handle */ \
278       /* this particular case. */ \
279       static void *operator new(size_t size, void *ptr) { return ::operator new(size,ptr); } \
280       void operator delete(void * memory, void *ptr) throw() { return ::operator delete(memory,ptr); } \
281       /* nothrow-new (returns zero instead of std::bad_alloc) */ \
282       EIGEN_MAKE_ALIGNED_OPERATOR_NEW_NOTHROW(NeedsToAlign) \
283       void operator delete(void *ptr, const std::nothrow_t&) throw() { \
284         Eigen::ei_conditional_aligned_free<NeedsToAlign>(ptr); \
285       } \
286       typedef void ei_operator_new_marker_type;
287 #else
288   #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
289 #endif
290
291 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(true)
292 #define EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar,Size) \
293   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(((Size)!=Eigen::Dynamic) && ((sizeof(Scalar)*(Size))%16==0))
294
295
296 /** \class aligned_allocator
297 *
298 * \brief stl compatible allocator to use with with 16 byte aligned types
299 *
300 * Example:
301 * \code
302 * // Matrix4f requires 16 bytes alignment:
303 * std::map< int, Matrix4f, std::less<int>, aligned_allocator<Matrix4f> > my_map_mat4;
304 * // Vector3f does not require 16 bytes alignment, no need to use Eigen's allocator:
305 * std::map< int, Vector3f > my_map_vec3;
306 * \endcode
307 *
308 */
309 template<class T>
310 class aligned_allocator
311 {
312 public:
313     typedef size_t    size_type;
314     typedef ptrdiff_t difference_type;
315     typedef T*        pointer;
316     typedef const T*  const_pointer;
317     typedef T&        reference;
318     typedef const T&  const_reference;
319     typedef T         value_type;
320
321     template<class U>
322     struct rebind
323     {
324         typedef aligned_allocator<U> other;
325     };
326
327     pointer address( reference value ) const
328     {
329         return &value;
330     }
331
332     const_pointer address( const_reference value ) const
333     {
334         return &value;
335     }
336
337     aligned_allocator() throw()
338     {
339     }
340
341     aligned_allocator( const aligned_allocator& ) throw()
342     {
343     }
344
345     template<class U>
346     aligned_allocator( const aligned_allocator<U>& ) throw()
347     {
348     }
349
350     ~aligned_allocator() throw()
351     {
352     }
353
354     size_type max_size() const throw()
355     {
356         return std::numeric_limits<size_type>::max();
357     }
358
359     pointer allocate( size_type num, const_pointer* hint = 0 )
360     {
361         static_cast<void>( hint ); // suppress unused variable warning
362         return static_cast<pointer>( ei_aligned_malloc( num * sizeof(T) ) );
363     }
364
365     void construct( pointer p, const T& value )
366     {
367         ::new( p ) T( value );
368     }
369
370     void destroy( pointer p )
371     {
372         p->~T();
373     }
374
375     void deallocate( pointer p, size_type /*num*/ )
376     {
377         ei_aligned_free( p );
378     }
379     
380     bool operator!=(const aligned_allocator<T>& other) const
381     { return false; }
382     
383     bool operator==(const aligned_allocator<T>& other) const
384     { return true; }
385 };
386
387 #endif // EIGEN_MEMORY_H