#ifndef _Vector #define _Vector /* Adapted from the Template Numerical Toolkit (TNT) Templated one-dimensional, numerical array which looks like a conventional C array. Elements are accessed via the A[i] or A(i) notation. Array assignment is by reference (i.e. shallow assignment). That is, B = A implies that the A and B point to the same array, so modifications to the elements of A will be reflected in B. If an independent copy is required, then B = A.Copy() can be used. Note that this facilitates returning arrays from functions without relying on compiler optimizations to eliminate extensive data copying. The indexing and layout of this array object makes it compatible with C and C++ algorithms that utilize the familiar C[i] notation. This includes numerous textbooks, such as Numercial Recipes, and various public domain codes. This class employs its own garbage collection via the use of reference counts. That is, whenever an internal array storage no longer has any references to it, it is destoryed. */ template class Vector { private: int n; // Size of vector T* p; // Underlying array int *RefCount; // Number of references void Initialize(); void Destroy(); public: string Name; Vector(); explicit Vector(int n); Vector(int n, const T &a); Vector(int n, T *a); inline Vector(const Vector &A); inline Vector & operator=(const T &a); inline Vector & operator=(const Vector &A); inline Vector & Ref(const Vector &A); Vector Copy() const; inline T& operator[](int i); inline const T& operator[](int i) const; inline T& operator()(int i); inline const T& operator()(int i) const; inline int Size() const; inline int GetRefCount() const; ~Vector(); T* Begin() const; T* End() const; }; /* Null constructor. Creates a 0-length (NULL) array (Reference count is also zero) */ template Vector::Vector() { n = 0; p = 0; RefCount = 0; Name = "NoName"; RefCount = new int; *RefCount = 1; } /* Copy constructor. Array data is NOT copied, but shared. Thus, in Vector B(A), subsequent changes to A will be reflected in B. For an indepent copy of A, use Vector B(A.Copy()), or B = A.Copy(), instead. */ template Vector::Vector(const Vector &A) { p = A.p; n = A.n; RefCount = A.RefCount; Name = A.Name; (*RefCount)++; } /* Create a new array (Vector) of length n, WITHOUT initializing array elements. To create an initialized array of constants, see Vector(n,Val). This version avoids the O(n) initialization overhead and is used just before manual assignment. */ template Vector::Vector(int n) { p = 0; this->n = n; RefCount = 0; if(n < 0) { cout << "Error in Vector(int n)\n"; cout << "n < 0\n"; cout << "n: " << n << "\n"; cout << "Halting Execution\n"; exit(0); } Name = "NoName"; Initialize(); RefCount = new int; *RefCount = 1; } /* Create a new array of length n, initializing array elements to constant specified by argument. Most often used to create an array of zeros, as in A(n,0.0). n - Dimension (length) of the new Vector. a - The constant value to set all elements of the new array to. */ template Vector::Vector(int n, const T &a) { p = 0; this->n = n; RefCount = 0; if(n < 0) { cout<< "Error in Vector::Vector(int n, const T &a)\n"; cout << "n < 0\n"; cout << "n: " << n << "\n"; cout << "Halting Execution\n"; exit(0); } Name = "NoName"; Initialize(); for(int i=0; i Vector::Vector(int n, T *a) { p = a; this->n = n; RefCount = 0; if(n < 0) { Print("Error in Vector::Vector(int n, T *a)"); Print("n < 0"); Print("n",n); HaltExecution(); } Name = "NoName"; RefCount = new int; *RefCount = 2; // This avoid destorying original data } /* A[i] indexes the ith element of A. The first element is A[0]. If _CheckBounds is defined, then the index is checked that it falls within the array bounds. */ template inline T& Vector::operator[](int i) { #ifdef _CheckBounds if(i < 0 || i >= n) { cout << "Error in Vector\n"; cout << "Index Out of Bounds\n"; cout << "Name: " << Name << "\n"; cout << "i: " << i << "\n"; cout << "n: " << n << "\n"; cout << "Halting Execution\n"; exit(0); } #endif return p[i]; } /* A[i] indexes the ith element of A. The first element is A[0]. If _CheckBounds is defined, then the index is checked that it fall within the array bounds. */ template inline const T& Vector::operator[](int i) const { #ifdef _CheckBounds if(i < 0 || i >= n) { cout << "Error in Vector\n"; cout << "Index Out of Bounds\n"; cout << "Name: " << Name << "\n"; cout << "i: " << i << "\n"; cout << "n: " << n << "\n"; cout << "Halting Execution\n"; exit(0); } #endif return p[i]; } /* A[i] indexes the ith element of A. The first element is A[0]. If _CheckBounds is defined, then the index is checked that it falls within the array bounds. */ template inline T& Vector::operator()(int i) { #ifdef _CheckBounds if(i < 0 || i >= n) { cout << "Error in Vector" << "\n"; cout << "Index Out of Bounds" << "\n"; cout << "Name: " << Name << "\n"; cout << "i: " << i << "\n"; cout << "n: " << n << "\n"; cout << "Halting Execution" << "\n"; exit(0); } #endif return p[i]; } /* A[i] indexes the ith element of A. The first element is A[0]. If _CheckBounds is defined, then the index is checked that it fall within the array bounds. */ template inline const T& Vector::operator()(int i) const { #ifdef _CheckBounds if(i < 0 || i >= n) { cout << "Error in Vector\n"; cout << "Index Out of Bounds\n"; cout << "Name: " << Name << "\n"; cout << "i: " << i << "\n"; cout << "n: " << n << "\n"; cout << "Halting Execution\n"; exit(0); } #endif return p[i]; } /* Assign all elemnts of A to a constant scalar */ template Vector & Vector::operator=(const T &a) { for(int i=0; i Vector Vector::Copy() const { Vector A(n); A.Name = Name; for(int i=0; i This is what operator= calls, and B = A and B.Ref(A) are equivalent operations. @return The new referenced array: in B.Ref(A), it returns B. */ template Vector & Vector::Ref(const Vector &A) { if(this != &A) { (*RefCount)--; if(*RefCount < 1) Destroy(); n = A.n; p = A.p; Name = A.Name; RefCount = A.RefCount; (*RefCount)++ ; } return *this; } /* B = A is shorthand notation for B.Ref(A) */ template Vector & Vector::operator=(const Vector &A) { return Ref(A); } /* @return the dimension (number of elements) of the array This is equivalent to Dim() */ template inline int Vector::Size() const { return n; } /* Return the number of arrays that share the same storage area as this one (Must be at least one) */ template inline int Vector::GetRefCount() const { return *RefCount; } /* Destructor */ template Vector::~Vector() { (*RefCount)--; if(*RefCount < 1) Destroy(); } /* Private internal functions */ template void Vector::Initialize() { try { p = new T[n]; } catch(bad_alloc ba) { cout << "Error in Vector\n"; cout << "Memory Allocation Failed\n"; cout << "n: " << n << "\n"; cout << "Memory per Entry: " << sizeof(T) << "\n"; cout << "Memory Needed in Megabytes:" << n*sizeof(T)/1e6 << "\n"; cout << "Halting Execution\n"; exit(0); } } template void Vector::Destroy() { if(p != 0) delete[] p; if(RefCount != 0) delete RefCount; } /* Begin */ template T* Vector::Begin() const { return &p[0]; } /* End */ template T* Vector::End() const { return &p[0] + n; } #endif