300 lines
7.0 KiB
C++
300 lines
7.0 KiB
C++
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
|
|
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
|
|
// reserved. See file COPYRIGHT for details.
|
|
//
|
|
// This file is part of the MFEM library. For more information and source code
|
|
// availability see http://mfem.googlecode.com.
|
|
//
|
|
// MFEM is free software; you can redistribute it and/or modify it under the
|
|
// terms of the GNU Lesser General Public License (as published by the Free
|
|
// Software Foundation) version 2.1 dated February 1999.
|
|
|
|
#ifndef MFEM_ARRAY
|
|
#define MFEM_ARRAY
|
|
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
#include "error.hpp"
|
|
|
|
using namespace std;
|
|
|
|
/// Base class for array container.
|
|
class BaseArray
|
|
{
|
|
protected:
|
|
/// Pointer to data
|
|
void *data;
|
|
/// Size of the array
|
|
int size;
|
|
/// Size of the allocated memory
|
|
int allocsize;
|
|
/** Increment of allocated memory on overflow,
|
|
inc = 0 doubles the array */
|
|
int inc;
|
|
|
|
BaseArray() { }
|
|
/// Creates array of asize elements of size elementsize
|
|
BaseArray(int asize, int ainc, int elmentsize);
|
|
/// Free the allocated memory
|
|
~BaseArray();
|
|
/** Increases the allocsize of the array to be at least minsize.
|
|
The current content of the array is copied to the newly allocated
|
|
space. minsize must be > abs(allocsize). */
|
|
void GrowSize(int minsize, int elementsize);
|
|
};
|
|
|
|
template <class T>
|
|
class Array;
|
|
|
|
template <class T>
|
|
void Swap(Array<T> &, Array<T> &);
|
|
|
|
/**
|
|
Abstract data type Array.
|
|
|
|
Array<T> is an automatically increasing array containing elements of the
|
|
generic type T. The allocated size may be larger then the logical size
|
|
of the array.
|
|
The elements can be accessed by the [] operator, the range is 0 to size-1.
|
|
*/
|
|
template <class T>
|
|
class Array : public BaseArray
|
|
{
|
|
public:
|
|
friend void Swap<T>(Array<T> &, Array<T> &);
|
|
|
|
/// Creates array of asize elements
|
|
inline Array(int asize = 0, int ainc = 0)
|
|
: BaseArray(asize, ainc, sizeof (T)) { }
|
|
|
|
/** Creates array using an existing c-array of asize elements;
|
|
allocsize is set to -asize to indicate that the data will not
|
|
be deleted. */
|
|
inline Array(T *_data, int asize, int ainc = 0)
|
|
{ data = _data; size = asize; allocsize = -asize; inc = ainc; }
|
|
|
|
/// Destructor
|
|
inline ~Array() { }
|
|
|
|
/// Return the data as 'T *'
|
|
inline operator T *() { return (T *)data; }
|
|
|
|
/// Returns the data
|
|
inline T *GetData() { return (T *)data; }
|
|
|
|
/// Changes the ownership of the the data
|
|
inline void StealData(T **p)
|
|
{ *p = (T*)data; data = 0; size = allocsize = 0; }
|
|
|
|
/// NULL-ifies the data
|
|
inline void LoseData() { data = 0; size = allocsize = 0; }
|
|
|
|
/// Make the Array own the data
|
|
void MakeDataOwner() { allocsize = abs(allocsize); }
|
|
|
|
/// Logical size of the array
|
|
inline int Size() const { return size; };
|
|
|
|
/// Change logical size of the array, keep existing entries
|
|
inline void SetSize(int nsize);
|
|
|
|
/// Access element
|
|
inline T & operator[](int i);
|
|
|
|
/// Access const element
|
|
inline const T &operator[](int i) const;
|
|
|
|
/// Append element to array, resize if necessary
|
|
inline int Append(const T & el);
|
|
|
|
/// Append another array to this array, resize if necessary
|
|
inline int Append(const Array<T> &els);
|
|
|
|
/// Prepend an element to the array, resize if necessary
|
|
inline int Prepend(const T &el);
|
|
|
|
/// Return the last element in the array
|
|
inline T &Last();
|
|
|
|
/// Append element when it is not yet in the array, return index
|
|
inline int Union(const T & el);
|
|
|
|
/// Delete the last entry
|
|
inline void DeleteLast() { size--; }
|
|
|
|
/// Delete the first 'el' entry
|
|
inline void DeleteFirst(const T &el);
|
|
|
|
/// Delete whole array
|
|
inline void DeleteAll();
|
|
|
|
/// Create a copy of the current array
|
|
inline void Copy(Array ©)
|
|
{
|
|
copy.SetSize(Size());
|
|
memcpy(copy.GetData(), GetData(), Size()*sizeof(T));
|
|
}
|
|
|
|
inline void GetSubArray(int offset, int sa_size, Array<T> &sa);
|
|
|
|
/// Prints array to stream with width elements per row
|
|
void Print(ostream &out, int width);
|
|
|
|
/// Prints array to stream out
|
|
void Save(ostream &out);
|
|
|
|
/** Finds the maximal element in the array.
|
|
(uses the comparison operator '<' for class T) */
|
|
T Max();
|
|
|
|
/// Sorts the array.
|
|
void Sort();
|
|
|
|
inline void operator=(const T &a);
|
|
|
|
private:
|
|
/// Array copy is not supported
|
|
Array<T> &operator=(Array<T> &);
|
|
/// Array copy is not supported
|
|
Array(const Array<T> &);
|
|
};
|
|
|
|
|
|
template <class T>
|
|
inline void Swap(Array<T> &a, Array<T> &b)
|
|
{
|
|
int s;
|
|
void *data;
|
|
|
|
data = a.data; a.data = b.data; b.data = data;
|
|
s = a.size; a.size = b.size; b.size = s;
|
|
s = a.allocsize; a.allocsize = b.allocsize; b.allocsize = s;
|
|
s = a.inc; a.inc = b.inc; b.inc = s;
|
|
}
|
|
|
|
template <class T>
|
|
inline void Array<T>::SetSize(int nsize)
|
|
{
|
|
if (nsize > abs(allocsize))
|
|
GrowSize(nsize, sizeof(T));
|
|
size = nsize;
|
|
}
|
|
|
|
template <class T>
|
|
inline T &Array<T>::operator[](int i)
|
|
{
|
|
#ifdef MFEM_DEBUG
|
|
if (i < 0 || i >= size)
|
|
{
|
|
cerr << "Access element " << i << " of array, size = " << size << endl;
|
|
mfem_error();
|
|
}
|
|
#endif
|
|
return ((T*)data)[i];
|
|
}
|
|
|
|
template <class T>
|
|
inline const T &Array<T>::operator[](int i) const
|
|
{
|
|
#ifdef MFEM_DEBUG
|
|
if (i < 0 || i >= size)
|
|
{
|
|
cerr << "Access element " << i << " of array, size = " << size << endl;
|
|
mfem_error();
|
|
}
|
|
#endif
|
|
return ((T*)data)[i];
|
|
}
|
|
|
|
template <class T>
|
|
inline int Array<T>::Append(const T &el)
|
|
{
|
|
SetSize(size+1);
|
|
((T*)data)[size-1] = el;
|
|
return size;
|
|
}
|
|
|
|
template <class T>
|
|
inline int Array<T>::Append(const Array<T> & els)
|
|
{
|
|
int old_size = size;
|
|
|
|
SetSize(size + els.Size());
|
|
for (int i = 0; i < els.Size(); i++)
|
|
((T*)data)[old_size+i] = els[i];
|
|
return size;
|
|
}
|
|
|
|
|
|
template <class T>
|
|
inline int Array<T>::Prepend(const T &el)
|
|
{
|
|
SetSize(size+1);
|
|
for (int i = size-1; i > 0; i--)
|
|
((T*)data)[i] = ((T*)data)[i-1];
|
|
((T*)data)[0] = el;
|
|
return size;
|
|
}
|
|
|
|
|
|
template <class T>
|
|
inline T &Array<T>::Last()
|
|
{
|
|
#ifdef MFEM_DEBUG
|
|
if (size < 1)
|
|
mfem_error("Array<T>::Last()");
|
|
#endif
|
|
return ((T*)data)[size-1];
|
|
}
|
|
|
|
template <class T>
|
|
inline int Array<T>::Union(const T &el)
|
|
{
|
|
int i = 0;
|
|
while ((i < size) && (((T*)data)[i] != el)) i++;
|
|
if (i == size)
|
|
Append(el);
|
|
return i;
|
|
}
|
|
|
|
template <class T>
|
|
inline void Array<T>::DeleteFirst(const T &el)
|
|
{
|
|
for (int i = 0; i < size; i++)
|
|
if (((T*)data)[i] == el)
|
|
{
|
|
for (i++; i < size; i++)
|
|
((T*)data)[i-1] = ((T*)data)[i];
|
|
size--;
|
|
return;
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
inline void Array<T>::DeleteAll()
|
|
{
|
|
if (allocsize > 0)
|
|
delete [] (char*)data;
|
|
data = NULL;
|
|
size = allocsize = 0;
|
|
}
|
|
|
|
template <class T>
|
|
inline void Array<T>::GetSubArray(int offset, int sa_size, Array<T> &sa)
|
|
{
|
|
sa.SetSize(sa_size);
|
|
for (int i = 0; i < sa_size; i++)
|
|
sa[i] = (*this)[offset+i];
|
|
}
|
|
|
|
template <class T>
|
|
inline void Array<T>::operator=(const T &a)
|
|
{
|
|
for (int i = 0; i < size; i++)
|
|
((T*)data)[i] = a;
|
|
}
|
|
|
|
#endif
|