Blender V2.61 - r43446

btAlignedObjectArray.h

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 
00017 #ifndef BT_OBJECT_ARRAY__
00018 #define BT_OBJECT_ARRAY__
00019 
00020 #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
00021 #include "btAlignedAllocator.h"
00022 
00028 
00029 #define BT_USE_PLACEMENT_NEW 1
00030 //#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
00031 
00032 #ifdef BT_USE_MEMCPY
00033 #include <memory.h>
00034 #include <string.h>
00035 #endif //BT_USE_MEMCPY
00036 
00037 #ifdef BT_USE_PLACEMENT_NEW
00038 #include <new> //for placement new
00039 #endif //BT_USE_PLACEMENT_NEW
00040 
00041 
00044 template <typename T> 
00045 //template <class T> 
00046 class btAlignedObjectArray
00047 {
00048     btAlignedAllocator<T , 16>  m_allocator;
00049 
00050     int                 m_size;
00051     int                 m_capacity;
00052     T*                  m_data;
00053     //PCK: added this line
00054     bool                m_ownsMemory;
00055 
00056     protected:
00057         SIMD_FORCE_INLINE   int allocSize(int size)
00058         {
00059             return (size ? size*2 : 1);
00060         }
00061         SIMD_FORCE_INLINE   void    copy(int start,int end, T* dest) const
00062         {
00063             int i;
00064             for (i=start;i<end;++i)
00065 #ifdef BT_USE_PLACEMENT_NEW
00066                 new (&dest[i]) T(m_data[i]);
00067 #else
00068                 dest[i] = m_data[i];
00069 #endif //BT_USE_PLACEMENT_NEW
00070         }
00071 
00072         SIMD_FORCE_INLINE   void    init()
00073         {
00074             //PCK: added this line
00075             m_ownsMemory = true;
00076             m_data = 0;
00077             m_size = 0;
00078             m_capacity = 0;
00079         }
00080         SIMD_FORCE_INLINE   void    destroy(int first,int last)
00081         {
00082             int i;
00083             for (i=first; i<last;i++)
00084             {
00085                 m_data[i].~T();
00086             }
00087         }
00088 
00089         SIMD_FORCE_INLINE   void* allocate(int size)
00090         {
00091             if (size)
00092                 return m_allocator.allocate(size);
00093             return 0;
00094         }
00095 
00096         SIMD_FORCE_INLINE   void    deallocate()
00097         {
00098             if(m_data)  {
00099                 //PCK: enclosed the deallocation in this block
00100                 if (m_ownsMemory)
00101                 {
00102                     m_allocator.deallocate(m_data);
00103                 }
00104                 m_data = 0;
00105             }
00106         }
00107 
00108     
00109 
00110 
00111     public:
00112         
00113         btAlignedObjectArray()
00114         {
00115             init();
00116         }
00117 
00118         ~btAlignedObjectArray()
00119         {
00120             clear();
00121         }
00122 
00124         btAlignedObjectArray(const btAlignedObjectArray& otherArray)
00125         {
00126             init();
00127 
00128             int otherSize = otherArray.size();
00129             resize (otherSize);
00130             otherArray.copy(0, otherSize, m_data);
00131         }
00132 
00133         
00134         
00136         SIMD_FORCE_INLINE   int size() const
00137         {   
00138             return m_size;
00139         }
00140         
00141         SIMD_FORCE_INLINE const T& at(int n) const
00142         {
00143             return m_data[n];
00144         }
00145 
00146         SIMD_FORCE_INLINE T& at(int n)
00147         {
00148             return m_data[n];
00149         }
00150 
00151         SIMD_FORCE_INLINE const T& operator[](int n) const
00152         {
00153             return m_data[n];
00154         }
00155 
00156         SIMD_FORCE_INLINE T& operator[](int n)
00157         {
00158             return m_data[n];
00159         }
00160         
00161 
00163         SIMD_FORCE_INLINE   void    clear()
00164         {
00165             destroy(0,size());
00166             
00167             deallocate();
00168             
00169             init();
00170         }
00171 
00172         SIMD_FORCE_INLINE   void    pop_back()
00173         {
00174             m_size--;
00175             m_data[m_size].~T();
00176         }
00177 
00180         SIMD_FORCE_INLINE   void    resize(int newsize, const T& fillData=T())
00181         {
00182             int curSize = size();
00183 
00184             if (newsize < curSize)
00185             {
00186                 for(int i = newsize; i < curSize; i++)
00187                 {
00188                     m_data[i].~T();
00189                 }
00190             } else
00191             {
00192                 if (newsize > size())
00193                 {
00194                     reserve(newsize);
00195                 }
00196 #ifdef BT_USE_PLACEMENT_NEW
00197                 for (int i=curSize;i<newsize;i++)
00198                 {
00199                     new ( &m_data[i]) T(fillData);
00200                 }
00201 #endif //BT_USE_PLACEMENT_NEW
00202 
00203             }
00204 
00205             m_size = newsize;
00206         }
00207     
00208         SIMD_FORCE_INLINE   T&  expandNonInitializing( )
00209         {   
00210             int sz = size();
00211             if( sz == capacity() )
00212             {
00213                 reserve( allocSize(size()) );
00214             }
00215             m_size++;
00216 
00217             return m_data[sz];      
00218         }
00219 
00220 
00221         SIMD_FORCE_INLINE   T&  expand( const T& fillValue=T())
00222         {   
00223             int sz = size();
00224             if( sz == capacity() )
00225             {
00226                 reserve( allocSize(size()) );
00227             }
00228             m_size++;
00229 #ifdef BT_USE_PLACEMENT_NEW
00230             new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
00231 #endif
00232 
00233             return m_data[sz];      
00234         }
00235 
00236 
00237         SIMD_FORCE_INLINE   void push_back(const T& _Val)
00238         {   
00239             int sz = size();
00240             if( sz == capacity() )
00241             {
00242                 reserve( allocSize(size()) );
00243             }
00244             
00245 #ifdef BT_USE_PLACEMENT_NEW
00246             new ( &m_data[m_size] ) T(_Val);
00247 #else
00248             m_data[size()] = _Val;          
00249 #endif //BT_USE_PLACEMENT_NEW
00250 
00251             m_size++;
00252         }
00253 
00254     
00256         SIMD_FORCE_INLINE   int capacity() const
00257         {   
00258             return m_capacity;
00259         }
00260         
00261         SIMD_FORCE_INLINE   void reserve(int _Count)
00262         {   // determine new minimum length of allocated storage
00263             if (capacity() < _Count)
00264             {   // not enough room, reallocate
00265                 T*  s = (T*)allocate(_Count);
00266 
00267                 copy(0, size(), s);
00268 
00269                 destroy(0,size());
00270 
00271                 deallocate();
00272                 
00273                 //PCK: added this line
00274                 m_ownsMemory = true;
00275 
00276                 m_data = s;
00277                 
00278                 m_capacity = _Count;
00279 
00280             }
00281         }
00282 
00283 
00284         class less
00285         {
00286             public:
00287 
00288                 bool operator() ( const T& a, const T& b )
00289                 {
00290                     return ( a < b );
00291                 }
00292         };
00293     
00294         template <typename L>
00295         void quickSortInternal(L CompareFunc,int lo, int hi)
00296         {
00297         //  lo is the lower index, hi is the upper index
00298         //  of the region of array a that is to be sorted
00299             int i=lo, j=hi;
00300             T x=m_data[(lo+hi)/2];
00301 
00302             //  partition
00303             do
00304             {    
00305                 while (CompareFunc(m_data[i],x)) 
00306                     i++; 
00307                 while (CompareFunc(x,m_data[j])) 
00308                     j--;
00309                 if (i<=j)
00310                 {
00311                     swap(i,j);
00312                     i++; j--;
00313                 }
00314             } while (i<=j);
00315 
00316             //  recursion
00317             if (lo<j) 
00318                 quickSortInternal( CompareFunc, lo, j);
00319             if (i<hi) 
00320                 quickSortInternal( CompareFunc, i, hi);
00321         }
00322 
00323 
00324         template <typename L>
00325         void quickSort(L CompareFunc)
00326         {
00327             //don't sort 0 or 1 elements
00328             if (size()>1)
00329             {
00330                 quickSortInternal(CompareFunc,0,size()-1);
00331             }
00332         }
00333 
00334 
00336         template <typename L>
00337         void downHeap(T *pArr, int k, int n,L CompareFunc)
00338         {
00339             /*  PRE: a[k+1..N] is a heap */
00340             /* POST:  a[k..N]  is a heap */
00341             
00342             T temp = pArr[k - 1];
00343             /* k has child(s) */
00344             while (k <= n/2) 
00345             {
00346                 int child = 2*k;
00347                 
00348                 if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
00349                 {
00350                     child++;
00351                 }
00352                 /* pick larger child */
00353                 if (CompareFunc(temp , pArr[child - 1]))
00354                 {
00355                     /* move child up */
00356                     pArr[k - 1] = pArr[child - 1];
00357                     k = child;
00358                 }
00359                 else
00360                 {
00361                     break;
00362                 }
00363             }
00364             pArr[k - 1] = temp;
00365         } /*downHeap*/
00366 
00367         void    swap(int index0,int index1)
00368         {
00369 #ifdef BT_USE_MEMCPY
00370             char    temp[sizeof(T)];
00371             memcpy(temp,&m_data[index0],sizeof(T));
00372             memcpy(&m_data[index0],&m_data[index1],sizeof(T));
00373             memcpy(&m_data[index1],temp,sizeof(T));
00374 #else
00375             T temp = m_data[index0];
00376             m_data[index0] = m_data[index1];
00377             m_data[index1] = temp;
00378 #endif //BT_USE_PLACEMENT_NEW
00379 
00380         }
00381 
00382     template <typename L>
00383     void heapSort(L CompareFunc)
00384     {
00385         /* sort a[0..N-1],  N.B. 0 to N-1 */
00386         int k;
00387         int n = m_size;
00388         for (k = n/2; k > 0; k--) 
00389         {
00390             downHeap(m_data, k, n, CompareFunc);
00391         }
00392 
00393         /* a[1..N] is now a heap */
00394         while ( n>=1 ) 
00395         {
00396             swap(0,n-1); /* largest of a[0..n-1] */
00397 
00398 
00399             n = n - 1;
00400             /* restore a[1..i-1] heap */
00401             downHeap(m_data, 1, n, CompareFunc);
00402         } 
00403     }
00404 
00406     int findBinarySearch(const T& key) const
00407     {
00408         int first = 0;
00409         int last = size()-1;
00410 
00411         //assume sorted array
00412         while (first <= last) {
00413             int mid = (first + last) / 2;  // compute mid point.
00414             if (key > m_data[mid]) 
00415                 first = mid + 1;  // repeat search in top half.
00416             else if (key < m_data[mid]) 
00417                 last = mid - 1; // repeat search in bottom half.
00418             else
00419                 return mid;     // found it. return position /////
00420         }
00421         return size();    // failed to find key
00422     }
00423 
00424 
00425     int findLinearSearch(const T& key) const
00426     {
00427         int index=size();
00428         int i;
00429 
00430         for (i=0;i<size();i++)
00431         {
00432             if (m_data[i] == key)
00433             {
00434                 index = i;
00435                 break;
00436             }
00437         }
00438         return index;
00439     }
00440 
00441     void    remove(const T& key)
00442     {
00443 
00444         int findIndex = findLinearSearch(key);
00445         if (findIndex<size())
00446         {
00447             swap( findIndex,size()-1);
00448             pop_back();
00449         }
00450     }
00451 
00452     //PCK: whole function
00453     void initializeFromBuffer(void *buffer, int size, int capacity)
00454     {
00455         clear();
00456         m_ownsMemory = false;
00457         m_data = (T*)buffer;
00458         m_size = size;
00459         m_capacity = capacity;
00460     }
00461 
00462     void copyFromArray(const btAlignedObjectArray& otherArray)
00463     {
00464         int otherSize = otherArray.size();
00465         resize (otherSize);
00466         otherArray.copy(0, otherSize, m_data);
00467     }
00468 
00469 };
00470 
00471 #endif //BT_OBJECT_ARRAY__