bullet3/examples/Experiments/ImplicitCloth/stan/array.h
erwincoumans ab8f16961e Code-style consistency improvement:
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files.
make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type.
This commit contains no other changes aside from adding and applying clang-format-all.sh
2018-09-23 14:17:31 -07:00

308 lines
5.6 KiB
C++

//
// Typical template dynamic array container class.
// By S Melax 1998
//
// anyone is free to use, inspect, learn from, or ignore
// the code here as they see fit.
//
// A very simple template array class.
// Its easiest to understand this array
// class by seeing how it is used in code.
//
// For example:
// for(i=0;i<myarray.count;i++)
// myarray[i] = somefunction(i);
//
// When the array runs out of room, it
// reallocates memory and doubles the size of its
// storage buffer. The reason for *doubleing* the amount of
// memory is so the order of any algorithm using this class
// is the same as it would be had you used a regular C array.
// The penalty for reallocating and copying
// For example consider adding n elements to a list.
// Lets sum the number of times elements are "copied".
// The worst case occurs when n=2^k+1 where k is integer.
// In this case we do a big reallocation when we add the last element.
// n elements are copied once, n/2 elements are copied twice,
// n/4 elements are copied 3 times, and so on ...
// total == n* (1+1/2 + 1/4 + 1/8 + ...) == n * 2
// So we do n*2 copies. Therefore adding n
// elements to an Array is still O(n).
// The memory usage is also of the same order as if a C array was used.
// An Array uses less than double the minimum needed space. Again, we
// see that we are within a small constant multiple.
//
// Why no "realloc" to avoid the copy when reallocating memory?
// You have a choice to either use malloc/free and friends
// or to use new/delete. Its bad mojo to mix these. new/delete was
// chosen to be C++ish and have the array elements constructors/destructors
// invoked as expected.
//
//
#ifndef SM_ARRAY_H
#define SM_ARRAY_H
#include <assert.h>
#include <stdio.h>
template <class Type>
class Array
{
public:
Array(int s = 0);
Array(Array<Type> &array);
~Array();
void allocate(int s);
void SetSize(int s);
void Pack();
Type &Add(Type);
void AddUnique(Type);
int Contains(Type);
void Insert(Type, int);
int IndexOf(Type);
void Remove(Type);
void DelIndex(int i);
Type &DelIndexWithLast(int i);
Type *element;
int count;
int array_size;
const Type &operator[](int i) const
{
assert(i >= 0 && i < count);
return element[i];
}
Type &operator[](int i)
{
assert(i >= 0 && i < count);
return element[i];
}
Type &Pop()
{
assert(count);
count--;
return element[count];
}
Array<Type> &copy(const Array<Type> &array);
Array<Type> &operator=(Array<Type> &array);
};
template <class Type>
Array<Type>::Array(int s)
{
if (s == -1) return;
count = 0;
array_size = 0;
element = NULL;
if (s)
{
allocate(s);
}
}
template <class Type>
Array<Type>::Array(Array<Type> &array)
{
count = 0;
array_size = 0;
element = NULL;
*this = array;
}
template <class Type>
Array<Type> &Array<Type>::copy(const Array<Type> &array)
{
assert(array.array_size >= 0);
count = 0;
for (int i = 0; i < array.count; i++)
{
Add(array[i]);
}
return *this;
}
template <class Type>
Array<Type> &Array<Type>::operator=(Array<Type> &array)
{
if (array.array_size < 0) // negative number means steal the data buffer instead of copying
{
delete[] element;
element = array.element;
array_size = -array.array_size;
count = array.count;
array.count = array.array_size = 0;
array.element = NULL;
return *this;
}
count = 0;
for (int i = 0; i < array.count; i++)
{
Add(array[i]);
}
return *this;
}
template <class Type>
Array<Type>::~Array()
{
if (element != NULL && array_size != 0)
{
delete[] element;
}
count = 0;
array_size = 0;
element = NULL;
}
template <class Type>
void Array<Type>::allocate(int s)
{
assert(s > 0);
assert(s >= count);
if (s == array_size) return;
Type *old = element;
array_size = s;
element = new Type[array_size];
assert(element);
for (int i = 0; i < count; i++)
{
element[i] = old[i];
}
if (old) delete[] old;
}
template <class Type>
void Array<Type>::SetSize(int s)
{
if (s == 0)
{
if (element)
{
delete[] element;
element = NULL;
}
array_size = s;
}
else
{
allocate(s);
}
count = s;
}
template <class Type>
void Array<Type>::Pack()
{
allocate(count);
}
template <class Type>
Type &Array<Type>::Add(Type t)
{
assert(count <= array_size);
if (count == array_size)
{
allocate((array_size) ? array_size * 2 : 16);
}
//int i;
//for(i=0;i<count;i++) {
// dissallow duplicates
// assert(element[i] != t);
//}
element[count++] = t;
return element[count - 1];
}
template <class Type>
int Array<Type>::Contains(Type t)
{
int i;
int found = 0;
for (i = 0; i < count; i++)
{
if (element[i] == t) found++;
}
return found;
}
template <class Type>
void Array<Type>::AddUnique(Type t)
{
if (!Contains(t)) Add(t);
}
template <class Type>
void Array<Type>::DelIndex(int i)
{
assert(i < count);
count--;
while (i < count)
{
element[i] = element[i + 1];
i++;
}
}
template <class Type>
Type &Array<Type>::DelIndexWithLast(int i)
{
assert(i < count);
count--;
if (i < count)
{
Type r = element[i];
element[i] = element[count];
element[count] = r;
}
return element[count];
}
template <class Type>
void Array<Type>::Remove(Type t)
{
int i;
for (i = 0; i < count; i++)
{
if (element[i] == t)
{
break;
}
}
assert(i < count); // assert object t is in the array.
DelIndex(i);
for (i = 0; i < count; i++)
{
assert(element[i] != t);
}
}
template <class Type>
void Array<Type>::Insert(Type t, int k)
{
int i = count;
Add(t); // to allocate space
while (i > k)
{
element[i] = element[i - 1];
i--;
}
assert(i == k);
element[k] = t;
}
template <class Type>
int Array<Type>::IndexOf(Type t)
{
int i;
for (i = 0; i < count; i++)
{
if (element[i] == t)
{
return i;
}
}
assert(0);
return -1;
}
#endif