#ifndef FILE_Array #define FILE_Array /**************************************************************************/ /* File: array.hpp */ /* Author: Joachim Schoeberl */ /* Date: 01. Jun. 95 */ /**************************************************************************/ // template <class T, int B1, int B2> class IndirectArray; /** A simple array container. Array represented by size and data-pointer. No memory allocation and deallocation, must be provided by user. Helper functions for printing. Optional range check by macro RANGE_CHECK */ template <class T, int BASE = 0> class FlatArray { protected: /// the size int size; /// the data T * data; public: /// provide size and memory FlatArray (int asize, T * adata) : size(asize), data(adata) { ; } /// the size int Size() const { return size; } int Begin() const { return BASE; } int End() const { return size+BASE; } /* /// access array. T & operator[] (int i) { #ifdef DEBUG if (i-BASE < 0 || i-BASE >= size) cout << "array<" << typeid(T).name() << "> out of range, i = " << i << ", s = " << size << endl; #endif return data[i-BASE]; } */ /// Access array. BASE-based T & operator[] (int i) const { #ifdef DEBUG if (i-BASE < 0 || i-BASE >= size) cout << "array<" << typeid(T).name() << "> out of range, i = " << i << ", s = " << size << endl; #endif return data[i-BASE]; } /* template <int B2> IndirectArray<T, BASE, B2> operator[] (const FlatArray<int, B2> & ind) { return IndirectArray<T, BASE, B2> (*this, ind); } */ /// Access array, one-based (old fashioned) T & Elem (int i) { #ifdef DEBUG if (i < 1 || i > size) cout << "Array<" << typeid(T).name() << ">::Elem out of range, i = " << i << ", s = " << size << endl; #endif return ((T*)data)[i-1]; } /// Access array, one-based (old fashioned) const T & Get (int i) const { #ifdef DEBUG if (i < 1 || i > size) cout << "Array<" << typeid(T).name() << ">::Get out of range, i = " << i << ", s = " << size << endl; #endif return ((const T*)data)[i-1]; } /// Access array, one-based (old fashioned) void Set (int i, const T & el) { #ifdef DEBUG if (i < 1 || i > size) cout << "Array<" << typeid(T).name() << ">::Set out of range, i = " << i << ", s = " << size << endl; #endif ((T*)data)[i-1] = el; } /// access first element T & First () const { return data[0]; } /// access last element. check by macro CHECK_RANGE T & Last () const { return data[size-1]; } /// Fill array with value val FlatArray & operator= (const T & val) { for (int i = 0; i < size; i++) data[i] = val; return *this; } /// takes range starting from position start of end-start elements const FlatArray<T> Range (int start, int end) { return FlatArray<T> (end-start, data+start); } /// first position of element elem, returns -1 if element not contained in array int Pos(const T & elem) const { int pos = -1; for(int i=0; pos==-1 && i < this->size; i++) if(elem == data[i]) pos = i; return pos; } /// does the array contain element elem ? bool Contains(const T & elem) const { return ( Pos(elem) >= 0 ); } }; // print array template <class T, int BASE> inline ostream & operator<< (ostream & s, const FlatArray<T,BASE> & a) { for (int i = a.Begin(); i < a.End(); i++) s << i << ": " << a[i] << endl; return s; } /** Dynamic array container. Array<T> is an automatically increasing array container. The allocated memory doubles on overflow. Either the container takes care of memory allocation and deallocation, or the user provides one block of data. */ template <class T, int BASE = 0> class Array : public FlatArray<T, BASE> { protected: /// physical size of array int allocsize; /// memory is responsibility of container bool ownmem; public: /// Generate array of logical and physical size asize explicit Array(int asize = 0) : FlatArray<T, BASE> (asize, asize ? new T[asize] : 0) { allocsize = asize; ownmem = 1; } /// Generate array in user data Array(int asize, T* adata) : FlatArray<T, BASE> (asize, adata) { allocsize = asize; ownmem = 0; } /// array copy explicit Array (const Array<T> & a2) : FlatArray<T, BASE> (a2.Size(), a2.Size() ? new T[a2.Size()] : 0) { allocsize = this->size; ownmem = 1; for (int i = BASE; i < this->size+BASE; i++) (*this)[i] = a2[i]; } /// if responsible, deletes memory ~Array() { if (ownmem) delete [] this->data; } /// Change logical size. If necessary, do reallocation. Keeps contents. void SetSize(int nsize) { if (nsize > allocsize) ReSize (nsize); this->size = nsize; } /// Change physical size. Keeps logical size. Keeps contents. void SetAllocSize (int nallocsize) { if (nallocsize > allocsize) ReSize (nallocsize); } /// Add element at end of array. reallocation if necessary. int Append (const T & el) { if (this->size == allocsize) ReSize (this->size+1); this->data[this->size] = el; this->size++; return this->size; } template <typename T2, int B2> void Append (FlatArray<T2, B2> a2) { if (this->size+a2.Size() > allocsize) ReSize (this->size+a2.Size()); for (int i = 0; i < a2.Size(); i++) this->data[this->size+i] = a2[i+B2]; this->size += a2.Size(); } /* template <int B1, int B2> void Append (const IndirectArray<T,B1,B2> & a2) { if (this->size+a2.Size() > allocsize) ReSize (this->size+a2.Size()); for (int i = 0; i < a2.Size(); i++) this->data[this->size+i] = a2[i+B2]; this->size += a2.Size(); } */ /// Delete element i (0-based). Move last element to position i. void Delete (int i) { #ifdef CHECK_Array_RANGE RangeCheck (i+1); #endif this->data[i] = this->data[this->size-1]; this->size--; // DeleteElement (i+1); } /// Delete element i (1-based). Move last element to position i. void DeleteElement (int i) { #ifdef CHECK_Array_RANGE RangeCheck (i); #endif this->data[i-1] = this->data[this->size-1]; this->size--; } /// Delete last element. void DeleteLast () { this->size--; } /// Deallocate memory void DeleteAll () { if (ownmem) delete [] this->data; this->data = 0; this->size = allocsize = 0; } /// Fill array with val Array & operator= (const T & val) { FlatArray<T, BASE>::operator= (val); return *this; } /// array copy Array & operator= (const Array & a2) { SetSize (a2.Size()); for (int i = BASE; i < this->size+BASE; i++) (*this)[i] = a2[i]; return *this; } /// array copy Array & operator= (const FlatArray<T> & a2) { SetSize (a2.Size()); for (int i = BASE; i < this->size+BASE; i++) (*this)[i] = a2[i]; return *this; } private: /// resize array, at least to size minsize. copy contents void ReSize (int minsize) { int nsize = 2 * allocsize; if (nsize < minsize) nsize = minsize; if (this->data) { T * p = new T[nsize]; int mins = (nsize < this->size) ? nsize : this->size; memcpy (p, this->data, mins * sizeof(T)); if (ownmem) delete [] this->data; ownmem = 1; this->data = p; } else { this->data = new T[nsize]; ownmem = 1; } allocsize = nsize; } }; template <class T, int S> class ArrayMem : public Array<T> { // T mem[S]; // Intel C++ calls dummy constructor // char mem[S*sizeof(T)]; double mem[(S*sizeof(T)+7) / 8]; public: /// Generate array of logical and physical size asize explicit ArrayMem(int asize = 0) : Array<T> (S, static_cast<T*> (static_cast<void*>(&mem[0]))) { this->size = asize; if (asize > S) { this->data = new T[asize]; this->ownmem = 1; } // this->SetSize (asize); } ArrayMem & operator= (const T & val) { Array<T>::operator= (val); return *this; } }; /* template <class T, int B1, int B2> class IndirectArray { const FlatArray<T, B1> & array; const FlatArray<int, B2> & ia; public: IndirectArray (const FlatArray<T,B1> & aa, const FlatArray<int, B2> & aia) : array(aa), ia(aia) { ; } int Size() const { return ia.Size(); } const T & operator[] (int i) const { return array[ia[i]]; } }; */ /// template <class T, int BASE = 0> class MoveableArray { int size; int allocsize; MoveableMem<T> data; public: MoveableArray() { size = allocsize = 0; data.SetName ("MoveableArray"); } MoveableArray(int asize) : size(asize), allocsize(asize), data(asize) { ; } ~MoveableArray () { ; } int Size() const { return size; } void SetSize(int nsize) { if (nsize > allocsize) { data.ReAlloc (nsize); allocsize = nsize; } size = nsize; } void SetAllocSize (int nallocsize) { data.ReAlloc (nallocsize); allocsize = nallocsize; } /// T & operator[] (int i) { return ((T*)data)[i-BASE]; } /// const T & operator[] (int i) const { return ((const T*)data)[i-BASE]; } /// T & Elem (int i) { return ((T*)data)[i-1]; } /// const T & Get (int i) const { return ((const T*)data)[i-1]; } /// void Set (int i, const T & el) { ((T*)data)[i-1] = el; } /// T & Last () { return ((T*)data)[size-1]; } /// const T & Last () const { return ((const T*)data)[size-1]; } /// int Append (const T & el) { if (size == allocsize) { SetAllocSize (2*allocsize+1); } ((T*)data)[size] = el; size++; return size; } /// void Delete (int i) { DeleteElement (i+1); } /// void DeleteElement (int i) { ((T*)data)[i-1] = ((T*)data)[size-1]; size--; } /// void DeleteLast () { size--; } /// void DeleteAll () { size = allocsize = 0; data.Free(); } /// void PrintMemInfo (ostream & ost) const { ost << Size() << " elements of size " << sizeof(T) << " = " << Size() * sizeof(T) << endl; } MoveableArray & operator= (const T & el) { for (int i = 0; i < size; i++) ((T*)data)[i] = el; return *this; } MoveableArray & Copy (const MoveableArray & a2) { SetSize (a2.Size()); for (int i = 0; i < this->size; i++) data[i] = a2.data[i]; return *this; } /// array copy MoveableArray & operator= (const MoveableArray & a2) { return Copy(a2); } void SetName (const char * aname) { data.SetName(aname); } private: /// //MoveableArray & operator= (MoveableArray &); //??? /// //MoveableArray (const MoveableArray &); //??? }; template <class T> inline ostream & operator<< (ostream & ost, MoveableArray<T> & a) { for (int i = 0; i < a.Size(); i++) ost << i << ": " << a[i] << endl; return ost; } /// bubble sort array template <class T> inline void BubbleSort (const FlatArray<T> & data) { T hv; for (int i = 0; i < data.Size(); i++) for (int j = i+1; j < data.Size(); j++) if (data[i] > data[j]) { hv = data[i]; data[i] = data[j]; data[j] = hv; } } /// bubble sort array template <class T, class S> inline void BubbleSort (FlatArray<T> & data, FlatArray<S> & slave) { T hv; S hvs; for (int i = 0; i < data.Size(); i++) for (int j = i+1; j < data.Size(); j++) if (data[i] > data[j]) { hv = data[i]; data[i] = data[j]; data[j] = hv; hvs = slave[i]; slave[i] = slave[j]; slave[j] = hvs; } } template <class T> void Intersection (const FlatArray<T> & in1, const FlatArray<T> & in2, Array<T> & out) { out.SetSize(0); for(int i=0; i<in1.Size(); i++) if(in2.Contains(in1[i])) out.Append(in1[i]); } template <class T> void Intersection (const FlatArray<T> & in1, const FlatArray<T> & in2, const FlatArray<T> & in3, Array<T> & out) { out.SetSize(0); for(int i=0; i<in1.Size(); i++) if(in2.Contains(in1[i]) && in3.Contains(in1[i])) out.Append(in1[i]); } #endif