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 #define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
00032 
00033 #ifdef BT_USE_MEMCPY
00034 #include <memory.h>
00035 #include <string.h>
00036 #endif //BT_USE_MEMCPY
00037 
00038 #ifdef BT_USE_PLACEMENT_NEW
00039 #include <new> //for placement new
00040 #endif //BT_USE_PLACEMENT_NEW
00041 
00042 
00045 template <typename T> 
00046 //template <class T> 
00047 class btAlignedObjectArray
00048 {
00049         btAlignedAllocator<T , 16>      m_allocator;
00050 
00051         int                                     m_size;
00052         int                                     m_capacity;
00053         T*                                      m_data;
00054         //PCK: added this line
00055         bool                            m_ownsMemory;
00056 
00057 #ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
00058 public:
00059         SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T> &other)
00060         {
00061                 copyFromArray(other);
00062                 return *this;
00063         }
00064 #else//BT_ALLOW_ARRAY_COPY_OPERATOR
00065 private:
00066                 SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T> &other);
00067 #endif//BT_ALLOW_ARRAY_COPY_OPERATOR
00068 
00069 protected:
00070                 SIMD_FORCE_INLINE       int     allocSize(int size)
00071                 {
00072                         return (size ? size*2 : 1);
00073                 }
00074                 SIMD_FORCE_INLINE       void    copy(int start,int end, T* dest) const
00075                 {
00076                         int i;
00077                         for (i=start;i<end;++i)
00078 #ifdef BT_USE_PLACEMENT_NEW
00079                                 new (&dest[i]) T(m_data[i]);
00080 #else
00081                                 dest[i] = m_data[i];
00082 #endif //BT_USE_PLACEMENT_NEW
00083                 }
00084 
00085                 SIMD_FORCE_INLINE       void    init()
00086                 {
00087                         //PCK: added this line
00088                         m_ownsMemory = true;
00089                         m_data = 0;
00090                         m_size = 0;
00091                         m_capacity = 0;
00092                 }
00093                 SIMD_FORCE_INLINE       void    destroy(int first,int last)
00094                 {
00095                         int i;
00096                         for (i=first; i<last;i++)
00097                         {
00098                                 m_data[i].~T();
00099                         }
00100                 }
00101 
00102                 SIMD_FORCE_INLINE       void* allocate(int size)
00103                 {
00104                         if (size)
00105                                 return m_allocator.allocate(size);
00106                         return 0;
00107                 }
00108 
00109                 SIMD_FORCE_INLINE       void    deallocate()
00110                 {
00111                         if(m_data)      {
00112                                 //PCK: enclosed the deallocation in this block
00113                                 if (m_ownsMemory)
00114                                 {
00115                                         m_allocator.deallocate(m_data);
00116                                 }
00117                                 m_data = 0;
00118                         }
00119                 }
00120 
00121         
00122 
00123 
00124         public:
00125                 
00126                 btAlignedObjectArray()
00127                 {
00128                         init();
00129                 }
00130 
00131                 ~btAlignedObjectArray()
00132                 {
00133                         clear();
00134                 }
00135 
00137                 btAlignedObjectArray(const btAlignedObjectArray& otherArray)
00138                 {
00139                         init();
00140 
00141                         int otherSize = otherArray.size();
00142                         resize (otherSize);
00143                         otherArray.copy(0, otherSize, m_data);
00144                 }
00145 
00146                 
00147                 
00149                 SIMD_FORCE_INLINE       int size() const
00150                 {       
00151                         return m_size;
00152                 }
00153                 
00154                 SIMD_FORCE_INLINE const T& at(int n) const
00155                 {
00156                         btAssert(n>=0);
00157                         btAssert(n<size());
00158                         return m_data[n];
00159                 }
00160 
00161                 SIMD_FORCE_INLINE T& at(int n)
00162                 {
00163                         btAssert(n>=0);
00164                         btAssert(n<size());
00165                         return m_data[n];
00166                 }
00167 
00168                 SIMD_FORCE_INLINE const T& operator[](int n) const
00169                 {
00170                         btAssert(n>=0);
00171                         btAssert(n<size());
00172                         return m_data[n];
00173                 }
00174 
00175                 SIMD_FORCE_INLINE T& operator[](int n)
00176                 {
00177                         btAssert(n>=0);
00178                         btAssert(n<size());
00179                         return m_data[n];
00180                 }
00181                 
00182 
00184                 SIMD_FORCE_INLINE       void    clear()
00185                 {
00186                         destroy(0,size());
00187                         
00188                         deallocate();
00189                         
00190                         init();
00191                 }
00192 
00193                 SIMD_FORCE_INLINE       void    pop_back()
00194                 {
00195                         btAssert(m_size>0);
00196                         m_size--;
00197                         m_data[m_size].~T();
00198                 }
00199 
00200 
00203                 SIMD_FORCE_INLINE       void    resizeNoInitialize(int newsize)
00204                 {
00205                         int curSize = size();
00206 
00207                         if (newsize < curSize)
00208                         {
00209                         } else
00210                         {
00211                                 if (newsize > size())
00212                                 {
00213                                         reserve(newsize);
00214                                 }
00215                                 //leave this uninitialized
00216                         }
00217                         m_size = newsize;
00218                 }
00219         
00220                 SIMD_FORCE_INLINE       void    resize(int newsize, const T& fillData=T())
00221                 {
00222                         int curSize = size();
00223 
00224                         if (newsize < curSize)
00225                         {
00226                                 for(int i = newsize; i < curSize; i++)
00227                                 {
00228                                         m_data[i].~T();
00229                                 }
00230                         } else
00231                         {
00232                                 if (newsize > size())
00233                                 {
00234                                         reserve(newsize);
00235                                 }
00236 #ifdef BT_USE_PLACEMENT_NEW
00237                                 for (int i=curSize;i<newsize;i++)
00238                                 {
00239                                         new ( &m_data[i]) T(fillData);
00240                                 }
00241 #endif //BT_USE_PLACEMENT_NEW
00242 
00243                         }
00244 
00245                         m_size = newsize;
00246                 }
00247                 SIMD_FORCE_INLINE       T&  expandNonInitializing( )
00248                 {       
00249                         int sz = size();
00250                         if( sz == capacity() )
00251                         {
00252                                 reserve( allocSize(size()) );
00253                         }
00254                         m_size++;
00255 
00256                         return m_data[sz];              
00257                 }
00258 
00259 
00260                 SIMD_FORCE_INLINE       T&  expand( const T& fillValue=T())
00261                 {       
00262                         int sz = size();
00263                         if( sz == capacity() )
00264                         {
00265                                 reserve( allocSize(size()) );
00266                         }
00267                         m_size++;
00268 #ifdef BT_USE_PLACEMENT_NEW
00269                         new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
00270 #endif
00271 
00272                         return m_data[sz];              
00273                 }
00274 
00275 
00276                 SIMD_FORCE_INLINE       void push_back(const T& _Val)
00277                 {       
00278                         int sz = size();
00279                         if( sz == capacity() )
00280                         {
00281                                 reserve( allocSize(size()) );
00282                         }
00283                         
00284 #ifdef BT_USE_PLACEMENT_NEW
00285                         new ( &m_data[m_size] ) T(_Val);
00286 #else
00287                         m_data[size()] = _Val;                  
00288 #endif //BT_USE_PLACEMENT_NEW
00289 
00290                         m_size++;
00291                 }
00292 
00293         
00295                 SIMD_FORCE_INLINE       int capacity() const
00296                 {       
00297                         return m_capacity;
00298                 }
00299                 
00300                 SIMD_FORCE_INLINE       void reserve(int _Count)
00301                 {       // determine new minimum length of allocated storage
00302                         if (capacity() < _Count)
00303                         {       // not enough room, reallocate
00304                                 T*      s = (T*)allocate(_Count);
00305 
00306                                 copy(0, size(), s);
00307 
00308                                 destroy(0,size());
00309 
00310                                 deallocate();
00311                                 
00312                                 //PCK: added this line
00313                                 m_ownsMemory = true;
00314 
00315                                 m_data = s;
00316                                 
00317                                 m_capacity = _Count;
00318 
00319                         }
00320                 }
00321 
00322 
00323                 class less
00324                 {
00325                         public:
00326 
00327                                 bool operator() ( const T& a, const T& b )
00328                                 {
00329                                         return ( a < b );
00330                                 }
00331                 };
00332         
00333 
00334                 template <typename L>
00335                 void quickSortInternal(const L& CompareFunc,int lo, int hi)
00336                 {
00337                 //  lo is the lower index, hi is the upper index
00338                 //  of the region of array a that is to be sorted
00339                         int i=lo, j=hi;
00340                         T x=m_data[(lo+hi)/2];
00341 
00342                         //  partition
00343                         do
00344                         {    
00345                                 while (CompareFunc(m_data[i],x)) 
00346                                         i++; 
00347                                 while (CompareFunc(x,m_data[j])) 
00348                                         j--;
00349                                 if (i<=j)
00350                                 {
00351                                         swap(i,j);
00352                                         i++; j--;
00353                                 }
00354                         } while (i<=j);
00355 
00356                         //  recursion
00357                         if (lo<j) 
00358                                 quickSortInternal( CompareFunc, lo, j);
00359                         if (i<hi) 
00360                                 quickSortInternal( CompareFunc, i, hi);
00361                 }
00362 
00363 
00364                 template <typename L>
00365                 void quickSort(const L& CompareFunc)
00366                 {
00367                         //don't sort 0 or 1 elements
00368                         if (size()>1)
00369                         {
00370                                 quickSortInternal(CompareFunc,0,size()-1);
00371                         }
00372                 }
00373 
00374 
00376                 template <typename L>
00377                 void downHeap(T *pArr, int k, int n, const L& CompareFunc)
00378                 {
00379                         /*  PRE: a[k+1..N] is a heap */
00380                         /* POST:  a[k..N]  is a heap */
00381                         
00382                         T temp = pArr[k - 1];
00383                         /* k has child(s) */
00384                         while (k <= n/2) 
00385                         {
00386                                 int child = 2*k;
00387                                 
00388                                 if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
00389                                 {
00390                                         child++;
00391                                 }
00392                                 /* pick larger child */
00393                                 if (CompareFunc(temp , pArr[child - 1]))
00394                                 {
00395                                         /* move child up */
00396                                         pArr[k - 1] = pArr[child - 1];
00397                                         k = child;
00398                                 }
00399                                 else
00400                                 {
00401                                         break;
00402                                 }
00403                         }
00404                         pArr[k - 1] = temp;
00405                 } /*downHeap*/
00406 
00407                 void    swap(int index0,int index1)
00408                 {
00409 #ifdef BT_USE_MEMCPY
00410                         char    temp[sizeof(T)];
00411                         memcpy(temp,&m_data[index0],sizeof(T));
00412                         memcpy(&m_data[index0],&m_data[index1],sizeof(T));
00413                         memcpy(&m_data[index1],temp,sizeof(T));
00414 #else
00415                         T temp = m_data[index0];
00416                         m_data[index0] = m_data[index1];
00417                         m_data[index1] = temp;
00418 #endif //BT_USE_PLACEMENT_NEW
00419 
00420                 }
00421 
00422         template <typename L>
00423         void heapSort(const L& CompareFunc)
00424         {
00425                 /* sort a[0..N-1],  N.B. 0 to N-1 */
00426                 int k;
00427                 int n = m_size;
00428                 for (k = n/2; k > 0; k--) 
00429                 {
00430                         downHeap(m_data, k, n, CompareFunc);
00431                 }
00432 
00433                 /* a[1..N] is now a heap */
00434                 while ( n>=1 ) 
00435                 {
00436                         swap(0,n-1); /* largest of a[0..n-1] */
00437 
00438 
00439                         n = n - 1;
00440                         /* restore a[1..i-1] heap */
00441                         downHeap(m_data, 1, n, CompareFunc);
00442                 } 
00443         }
00444 
00446         int     findBinarySearch(const T& key) const
00447         {
00448                 int first = 0;
00449                 int last = size()-1;
00450 
00451                 //assume sorted array
00452                 while (first <= last) {
00453                         int mid = (first + last) / 2;  // compute mid point.
00454                         if (key > m_data[mid]) 
00455                                 first = mid + 1;  // repeat search in top half.
00456                         else if (key < m_data[mid]) 
00457                                 last = mid - 1; // repeat search in bottom half.
00458                         else
00459                                 return mid;     // found it. return position /////
00460                 }
00461                 return size();    // failed to find key
00462         }
00463 
00464 
00465         int     findLinearSearch(const T& key) const
00466         {
00467                 int index=size();
00468                 int i;
00469 
00470                 for (i=0;i<size();i++)
00471                 {
00472                         if (m_data[i] == key)
00473                         {
00474                                 index = i;
00475                                 break;
00476                         }
00477                 }
00478                 return index;
00479         }
00480 
00481         void    remove(const T& key)
00482         {
00483 
00484                 int findIndex = findLinearSearch(key);
00485                 if (findIndex<size())
00486                 {
00487                         swap( findIndex,size()-1);
00488                         pop_back();
00489                 }
00490         }
00491 
00492         //PCK: whole function
00493         void initializeFromBuffer(void *buffer, int size, int capacity)
00494         {
00495                 clear();
00496                 m_ownsMemory = false;
00497                 m_data = (T*)buffer;
00498                 m_size = size;
00499                 m_capacity = capacity;
00500         }
00501 
00502         void copyFromArray(const btAlignedObjectArray& otherArray)
00503         {
00504                 int otherSize = otherArray.size();
00505                 resize (otherSize);
00506                 otherArray.copy(0, otherSize, m_data);
00507         }
00508 
00509 };
00510 
00511 #endif //BT_OBJECT_ARRAY__