Bullet Collision Detection & Physics Library
btAlignedObjectArray.h
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 #ifndef BT_OBJECT_ARRAY__
17 #define BT_OBJECT_ARRAY__
18 
19 #include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
20 #include "btAlignedAllocator.h"
21 
27 
28 #define BT_USE_PLACEMENT_NEW 1
29 //#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...
30 #define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
31 
32 #ifdef BT_USE_MEMCPY
33 #include <memory.h>
34 #include <string.h>
35 #endif //BT_USE_MEMCPY
36 
37 #ifdef BT_USE_PLACEMENT_NEW
38 #include <new> //for placement new
39 #endif //BT_USE_PLACEMENT_NEW
40 
41 // The register keyword is deprecated in C++11 so don't use it.
42 #if __cplusplus > 199711L
43 #define BT_REGISTER
44 #else
45 #define BT_REGISTER register
46 #endif
47 
50 template <typename T>
51 //template <class T>
53 {
55 
56  int m_size;
58  T* m_data;
59  //PCK: added this line
61 
62 #ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
63 public:
65  {
66  copyFromArray(other);
67  return *this;
68  }
69 #else //BT_ALLOW_ARRAY_COPY_OPERATOR
70 private:
72 #endif //BT_ALLOW_ARRAY_COPY_OPERATOR
73 
74 protected:
76  {
77  return (size ? size * 2 : 1);
78  }
79  SIMD_FORCE_INLINE void copy(int start, int end, T* dest) const
80  {
81  int i;
82  for (i = start; i < end; ++i)
84  new (&dest[i]) T(m_data[i]);
85 #else
86  dest[i] = m_data[i];
87 #endif //BT_USE_PLACEMENT_NEW
88  }
89 
91  {
92  //PCK: added this line
93  m_ownsMemory = true;
94  m_data = 0;
95  m_size = 0;
96  m_capacity = 0;
97  }
98  SIMD_FORCE_INLINE void destroy(int first, int last)
99  {
100  int i;
101  for (i = first; i < last; i++)
102  {
103  m_data[i].~T();
104  }
105  }
106 
108  {
109  if (size)
110  return m_allocator.allocate(size);
111  return 0;
112  }
113 
115  {
116  if (m_data)
117  {
118  //PCK: enclosed the deallocation in this block
119  if (m_ownsMemory)
120  {
122  }
123  m_data = 0;
124  }
125  }
126 
127 public:
129  {
130  init();
131  }
132 
134  {
135  clear();
136  }
137 
140  {
141  init();
142 
143  int otherSize = otherArray.size();
144  resize(otherSize);
145  otherArray.copy(0, otherSize, m_data);
146  }
147 
150  {
151  return m_size;
152  }
153 
154  SIMD_FORCE_INLINE const T& at(int n) const
155  {
156  btAssert(n >= 0);
157  btAssert(n < size());
158  return m_data[n];
159  }
160 
162  {
163  btAssert(n >= 0);
164  btAssert(n < size());
165  return m_data[n];
166  }
167 
168  SIMD_FORCE_INLINE const T& operator[](int n) const
169  {
170  btAssert(n >= 0);
171  btAssert(n < size());
172  return m_data[n];
173  }
174 
176  {
177  btAssert(n >= 0);
178  btAssert(n < size());
179  return m_data[n];
180  }
181 
184  {
185  destroy(0, size());
186 
187  deallocate();
188 
189  init();
190  }
191 
193  {
194  btAssert(m_size > 0);
195  m_size--;
196  m_data[m_size].~T();
197  }
198 
202  {
203  if (newsize > size())
204  {
205  reserve(newsize);
206  }
207  m_size = newsize;
208  }
209 
210  SIMD_FORCE_INLINE void resize(int newsize, const T& fillData = T())
211  {
212  const BT_REGISTER int curSize = size();
213 
214  if (newsize < curSize)
215  {
216  for (int i = newsize; i < curSize; i++)
217  {
218  m_data[i].~T();
219  }
220  }
221  else
222  {
223  if (newsize > curSize)
224  {
225  reserve(newsize);
226  }
227 #ifdef BT_USE_PLACEMENT_NEW
228  for (int i = curSize; i < newsize; i++)
229  {
230  new (&m_data[i]) T(fillData);
231  }
232 #endif //BT_USE_PLACEMENT_NEW
233  }
234 
235  m_size = newsize;
236  }
238  {
239  const BT_REGISTER int sz = size();
240  if (sz == capacity())
241  {
242  reserve(allocSize(size()));
243  }
244  m_size++;
245 
246  return m_data[sz];
247  }
248 
249  SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
250  {
251  const BT_REGISTER int sz = size();
252  if (sz == capacity())
253  {
254  reserve(allocSize(size()));
255  }
256  m_size++;
257 #ifdef BT_USE_PLACEMENT_NEW
258  new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
259 #endif
260 
261  return m_data[sz];
262  }
263 
264  SIMD_FORCE_INLINE void push_back(const T& _Val)
265  {
266  const BT_REGISTER int sz = size();
267  if (sz == capacity())
268  {
269  reserve(allocSize(size()));
270  }
271 
272 #ifdef BT_USE_PLACEMENT_NEW
273  new (&m_data[m_size]) T(_Val);
274 #else
275  m_data[size()] = _Val;
276 #endif //BT_USE_PLACEMENT_NEW
277 
278  m_size++;
279  }
280 
283  {
284  return m_capacity;
285  }
286 
287  SIMD_FORCE_INLINE void reserve(int _Count)
288  { // determine new minimum length of allocated storage
289  if (capacity() < _Count)
290  { // not enough room, reallocate
291  T* s = (T*)allocate(_Count);
292 
293  copy(0, size(), s);
294 
295  destroy(0, size());
296 
297  deallocate();
298 
299  //PCK: added this line
300  m_ownsMemory = true;
301 
302  m_data = s;
303 
304  m_capacity = _Count;
305  }
306  }
307 
308  class less
309  {
310  public:
311  bool operator()(const T& a, const T& b) const
312  {
313  return (a < b);
314  }
315  };
316 
317  template <typename L>
318  void quickSortInternal(const L& CompareFunc, int lo, int hi)
319  {
320  // lo is the lower index, hi is the upper index
321  // of the region of array a that is to be sorted
322  int i = lo, j = hi;
323  T x = m_data[(lo + hi) / 2];
324 
325  // partition
326  do
327  {
328  while (CompareFunc(m_data[i], x))
329  i++;
330  while (CompareFunc(x, m_data[j]))
331  j--;
332  if (i <= j)
333  {
334  swap(i, j);
335  i++;
336  j--;
337  }
338  } while (i <= j);
339 
340  // recursion
341  if (lo < j)
342  quickSortInternal(CompareFunc, lo, j);
343  if (i < hi)
344  quickSortInternal(CompareFunc, i, hi);
345  }
346 
347  template <typename L>
348  void quickSort(const L& CompareFunc)
349  {
350  //don't sort 0 or 1 elements
351  if (size() > 1)
352  {
353  quickSortInternal(CompareFunc, 0, size() - 1);
354  }
355  }
356 
358  template <typename L>
359  void downHeap(T* pArr, int k, int n, const L& CompareFunc)
360  {
361  /* PRE: a[k+1..N] is a heap */
362  /* POST: a[k..N] is a heap */
363 
364  T temp = pArr[k - 1];
365  /* k has child(s) */
366  while (k <= n / 2)
367  {
368  int child = 2 * k;
369 
370  if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
371  {
372  child++;
373  }
374  /* pick larger child */
375  if (CompareFunc(temp, pArr[child - 1]))
376  {
377  /* move child up */
378  pArr[k - 1] = pArr[child - 1];
379  k = child;
380  }
381  else
382  {
383  break;
384  }
385  }
386  pArr[k - 1] = temp;
387  } /*downHeap*/
388 
389  void swap(int index0, int index1)
390  {
391 #ifdef BT_USE_MEMCPY
392  char temp[sizeof(T)];
393  memcpy(temp, &m_data[index0], sizeof(T));
394  memcpy(&m_data[index0], &m_data[index1], sizeof(T));
395  memcpy(&m_data[index1], temp, sizeof(T));
396 #else
397  T temp = m_data[index0];
398  m_data[index0] = m_data[index1];
399  m_data[index1] = temp;
400 #endif //BT_USE_PLACEMENT_NEW
401  }
402 
403  template <typename L>
404  void heapSort(const L& CompareFunc)
405  {
406  /* sort a[0..N-1], N.B. 0 to N-1 */
407  int k;
408  int n = m_size;
409  for (k = n / 2; k > 0; k--)
410  {
411  downHeap(m_data, k, n, CompareFunc);
412  }
413 
414  /* a[1..N] is now a heap */
415  while (n >= 1)
416  {
417  swap(0, n - 1); /* largest of a[0..n-1] */
418 
419  n = n - 1;
420  /* restore a[1..i-1] heap */
421  downHeap(m_data, 1, n, CompareFunc);
422  }
423  }
424 
426  int findBinarySearch(const T& key) const
427  {
428  int first = 0;
429  int last = size() - 1;
430 
431  //assume sorted array
432  while (first <= last)
433  {
434  int mid = (first + last) / 2; // compute mid point.
435  if (key > m_data[mid])
436  first = mid + 1; // repeat search in top half.
437  else if (key < m_data[mid])
438  last = mid - 1; // repeat search in bottom half.
439  else
440  return mid; // found it. return position /////
441  }
442  return size(); // failed to find key
443  }
444 
445  int findLinearSearch(const T& key) const
446  {
447  int index = size();
448  int i;
449 
450  for (i = 0; i < size(); i++)
451  {
452  if (m_data[i] == key)
453  {
454  index = i;
455  break;
456  }
457  }
458  return index;
459  }
460 
461  // If the key is not in the array, return -1 instead of 0,
462  // since 0 also means the first element in the array.
463  int findLinearSearch2(const T& key) const
464  {
465  int index = -1;
466  int i;
467 
468  for (i = 0; i < size(); i++)
469  {
470  if (m_data[i] == key)
471  {
472  index = i;
473  break;
474  }
475  }
476  return index;
477  }
478 
479  void removeAtIndex(int index)
480  {
481  if (index < size())
482  {
483  swap(index, size() - 1);
484  pop_back();
485  }
486  }
487  void remove(const T& key)
488  {
489  int findIndex = findLinearSearch(key);
490  removeAtIndex(findIndex);
491  }
492 
493  //PCK: whole function
494  void initializeFromBuffer(void* buffer, int size, int capacity)
495  {
496  clear();
497  m_ownsMemory = false;
498  m_data = (T*)buffer;
499  m_size = size;
501  }
502 
503  void copyFromArray(const btAlignedObjectArray& otherArray)
504  {
505  int otherSize = otherArray.size();
506  resize(otherSize);
507  otherArray.copy(0, otherSize, m_data);
508  }
509 };
510 
511 #endif //BT_OBJECT_ARRAY__
#define BT_REGISTER
void push_back(const T &_Val)
void deallocate(pointer ptr)
int findLinearSearch2(const T &key) const
void copy(int start, int end, T *dest) const
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
bool operator()(const T &a, const T &b) const
int findLinearSearch(const T &key) const
const T & operator[](int n) const
void resizeNoInitialize(int newsize)
resize changes the number of elements in the array.
void destroy(int first, int last)
#define btAssert(x)
Definition: btScalar.h:133
const T & at(int n) const
#define SIMD_FORCE_INLINE
Definition: btScalar.h:83
void copyFromArray(const btAlignedObjectArray &otherArray)
void downHeap(T *pArr, int k, int n, const L &CompareFunc)
heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
void swap(int index0, int index1)
void heapSort(const L &CompareFunc)
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
void removeAtIndex(int index)
#define BT_USE_PLACEMENT_NEW
If the platform doesn&#39;t support placement new, you can disable BT_USE_PLACEMENT_NEW then the btAligne...
int capacity() const
return the pre-allocated (reserved) elements, this is at least as large as the total number of elemen...
void initializeFromBuffer(void *buffer, int size, int capacity)
int size() const
return the number of elements in the array
btAlignedAllocator< T, 16 > m_allocator
btAlignedObjectArray(const btAlignedObjectArray &otherArray)
Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
void resize(int newsize, const T &fillData=T())
btAlignedObjectArray< T > & operator=(const btAlignedObjectArray< T > &other)
int findBinarySearch(const T &key) const
non-recursive binary search, assumes sorted array
T & expand(const T &fillValue=T())
pointer allocate(size_type n, const_pointer *hint=0)
void quickSortInternal(const L &CompareFunc, int lo, int hi)
void quickSort(const L &CompareFunc)