bullet3/examples/Experiments/ImplicitCloth/stan/array.h

308 lines
5.6 KiB
C
Raw Normal View History

2015-04-30 20:36:39 +00:00
//
// Typical template dynamic array container class.
// By S Melax 1998
//
2015-04-30 20:36:39 +00:00
// anyone is free to use, inspect, learn from, or ignore
// the code here as they see fit.
2015-04-30 20:36:39 +00:00
//
// 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++)
2015-04-30 20:36:39 +00:00
// myarray[i] = somefunction(i);
//
// When the array runs out of room, it
2015-04-30 20:36:39 +00:00
// 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
2015-04-30 20:36:39 +00:00
// 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.
2015-04-30 20:36:39 +00:00
// 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
2015-04-30 20:36:39 +00:00
// 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
2015-04-30 20:36:39 +00:00
// 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
2015-04-30 20:36:39 +00:00
// 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
2015-04-30 20:36:39 +00:00
// 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];
}
2015-04-30 20:36:39 +00:00
Array<Type> &copy(const Array<Type> &array);
Array<Type> &operator=(Array<Type> &array);
};
template <class Type>
Array<Type>::Array(int s)
2015-04-30 20:36:39 +00:00
{
if (s == -1) return;
count = 0;
2015-04-30 20:36:39 +00:00
array_size = 0;
element = NULL;
if (s)
{
2015-04-30 20:36:39 +00:00
allocate(s);
}
}
template <class Type>
Array<Type>::Array(Array<Type> &array)
2015-04-30 20:36:39 +00:00
{
count = 0;
2015-04-30 20:36:39 +00:00
array_size = 0;
element = NULL;
*this = array;
}
template <class Type>
Array<Type> &Array<Type>::copy(const Array<Type> &array)
2015-04-30 20:36:39 +00:00
{
assert(array.array_size >= 0);
count = 0;
for (int i = 0; i < array.count; i++)
{
2015-04-30 20:36:39 +00:00
Add(array[i]);
}
return *this;
}
template <class Type>
Array<Type> &Array<Type>::operator=(Array<Type> &array)
2015-04-30 20:36:39 +00:00
{
if (array.array_size < 0) // negative number means steal the data buffer instead of copying
2015-04-30 20:36:39 +00:00
{
delete[] element;
2015-04-30 20:36:39 +00:00
element = array.element;
array_size = -array.array_size;
count = array.count;
array.count = array.array_size = 0;
2015-04-30 20:36:39 +00:00
array.element = NULL;
return *this;
}
count = 0;
for (int i = 0; i < array.count; i++)
{
2015-04-30 20:36:39 +00:00
Add(array[i]);
}
return *this;
}
template <class Type>
Array<Type>::~Array()
2015-04-30 20:36:39 +00:00
{
if (element != NULL && array_size != 0)
{
delete[] element;
}
count = 0;
array_size = 0;
element = NULL;
2015-04-30 20:36:39 +00:00
}
template <class Type>
void Array<Type>::allocate(int s)
2015-04-30 20:36:39 +00:00
{
assert(s > 0);
assert(s >= count);
if (s == array_size) return;
2015-04-30 20:36:39 +00:00
Type *old = element;
array_size = s;
2015-04-30 20:36:39 +00:00
element = new Type[array_size];
assert(element);
for (int i = 0; i < count; i++)
{
element[i] = old[i];
2015-04-30 20:36:39 +00:00
}
if (old) delete[] old;
2015-04-30 20:36:39 +00:00
}
template <class Type>
void Array<Type>::SetSize(int s)
2015-04-30 20:36:39 +00:00
{
if (s == 0)
{
if (element)
{
delete[] element;
element = NULL;
}
2015-04-30 20:36:39 +00:00
array_size = s;
}
else
{
allocate(s);
}
count = s;
2015-04-30 20:36:39 +00:00
}
template <class Type>
void Array<Type>::Pack()
2015-04-30 20:36:39 +00:00
{
allocate(count);
}
template <class Type>
Type &Array<Type>::Add(Type t)
2015-04-30 20:36:39 +00:00
{
assert(count <= array_size);
if (count == array_size)
{
allocate((array_size) ? array_size * 2 : 16);
2015-04-30 20:36:39 +00:00
}
//int i;
//for(i=0;i<count;i++) {
// dissallow duplicates
2015-04-30 20:36:39 +00:00
// assert(element[i] != t);
//}
element[count++] = t;
return element[count - 1];
2015-04-30 20:36:39 +00:00
}
template <class Type>
int Array<Type>::Contains(Type t)
2015-04-30 20:36:39 +00:00
{
int i;
int found = 0;
for (i = 0; i < count; i++)
{
if (element[i] == t) found++;
2015-04-30 20:36:39 +00:00
}
return found;
}
template <class Type>
void Array<Type>::AddUnique(Type t)
2015-04-30 20:36:39 +00:00
{
if (!Contains(t)) Add(t);
2015-04-30 20:36:39 +00:00
}
template <class Type>
void Array<Type>::DelIndex(int i)
2015-04-30 20:36:39 +00:00
{
assert(i < count);
2015-04-30 20:36:39 +00:00
count--;
while (i < count)
{
element[i] = element[i + 1];
2015-04-30 20:36:39 +00:00
i++;
}
}
template <class Type>
Type &Array<Type>::DelIndexWithLast(int i)
2015-04-30 20:36:39 +00:00
{
assert(i < count);
2015-04-30 20:36:39 +00:00
count--;
if (i < count)
{
Type r = element[i];
2015-04-30 20:36:39 +00:00
element[i] = element[count];
element[count] = r;
2015-04-30 20:36:39 +00:00
}
return element[count];
}
template <class Type>
void Array<Type>::Remove(Type t)
2015-04-30 20:36:39 +00:00
{
int i;
for (i = 0; i < count; i++)
{
if (element[i] == t)
{
2015-04-30 20:36:39 +00:00
break;
}
}
assert(i < count); // assert object t is in the array.
2015-04-30 20:36:39 +00:00
DelIndex(i);
for (i = 0; i < count; i++)
{
2015-04-30 20:36:39 +00:00
assert(element[i] != t);
}
}
template <class Type>
void Array<Type>::Insert(Type t, int k)
2015-04-30 20:36:39 +00:00
{
int i = count;
Add(t); // to allocate space
while (i > k)
{
element[i] = element[i - 1];
2015-04-30 20:36:39 +00:00
i--;
}
assert(i == k);
element[k] = t;
2015-04-30 20:36:39 +00:00
}
template <class Type>
int Array<Type>::IndexOf(Type t)
2015-04-30 20:36:39 +00:00
{
int i;
for (i = 0; i < count; i++)
{
if (element[i] == t)
{
2015-04-30 20:36:39 +00:00
return i;
}
}
assert(0);
return -1;
}
#endif