00001 // Copyright (C) 2007 Peter Carbonetto. All Rights Reserved. 00002 // This code is published under the Common Public License. 00003 // 00004 // Author: Peter Carbonetto 00005 // Dept. of Computer Science 00006 // University of British Columbia 00007 // May 19, 2007 00008 00009 #ifndef INCLUDE_ARRAY 00010 #define INCLUDE_ARRAY 00011 00012 #include "matlabexception.h" 00013 #include <string.h> 00014 00015 // Function definitions. 00016 // --------------------------------------------------------------- 00017 template <class Type> void copymemory (const Type* source, Type* dest, 00018 int length) { 00019 memcpy(dest,source,sizeof(Type)*length); 00020 } 00021 00022 // Class Array 00023 // --------------------------------------------------------------- 00024 // An Array object stores a collection of ordered elements. The key 00025 // aspect of Array objects is that they do not necessarily achieve 00026 // encapsulation; they do not necessarily retain independent 00027 // ownership of their data. That is, the data could be modified 00028 // externally by another agent. This behaviour is determined by the 00029 // data member "owner". If "owner" is false, the array does not take 00030 // care of allocation and deallocation of the data in memory. 00031 // 00032 // Copy assignment behaves different than usual---it copies the 00033 // data, but requires that the destination already have the proper 00034 // resources allocated in memory. 00035 // 00036 // The copy constructor performs a shallow copy. 00037 template <class Type> class Array { 00038 public: 00039 00040 // This constructor allocates memory for an array of elements of 00041 // the specificed length. 00042 explicit Array (int length); 00043 00044 // This constructor is set to point to an already existing 00045 // array. As such, it does not gain ownership of the elements. 00046 Array (Type* data, int length); 00047 00048 // The copy constructor performs a shallow copy, so that both 00049 // arrays share the same copy of the data. 00050 Array (const Array<Type>& source); 00051 00052 // The destructor. 00053 ~Array(); 00054 00055 // Set all the elements of the array to the specified value. 00056 void setvalue (const Type& value); 00057 00058 // Copy the elements to from the source array. Both the source and 00059 // destination array must have the same length. 00060 void inject (const Type* source); 00061 void inject (const Array<Type>& source); 00062 Array<Type>& operator= (const Type* source); 00063 Array<Type>& operator= (const Array<Type>& source); 00064 00065 // Copy the elements to the location in memory pointed to by 00066 // "dest". It is assumed that sufficient memory is allocated for 00067 // the destination. 00068 void copyto (Type* dest) const; 00069 00070 // Get the number of elements in the array. 00071 int length() const { return n; }; 00072 00073 // Elements of an array A can be accessed the subscript operator; 00074 // e.g. A[i]. For the sake of efficiency, no checks are made to 00075 // ensure that the subscripting is legal. It is up to the user to 00076 // ensure that i is non-negative and less than A.length(). Note 00077 // that subscripts, as per C++ convention, start at 0. 00078 Type& operator[] (int i); 00079 const Type& operator[] (int i) const; 00080 00081 // Returns true if the two arrays have the same dimensions 00082 // (i.e. the same lengths). 00083 bool operator== (const Array<Type>& a) const { return n == a.n; }; 00084 bool operator!= (const Array<Type>& a) const { return !(*this == a); }; 00085 00086 protected: 00087 Type* elems; 00088 int n; // The number of elements in the array. 00089 bool owner; // Whether the object has ownership of the data. 00090 }; 00091 00092 // Function definitions for class Array. 00093 // ----------------------------------------------------------------- 00094 template <class Type> Array<Type>::Array (int length) { 00095 n = length; 00096 owner = true; 00097 elems = 0; 00098 elems = new Type[length]; 00099 } 00100 00101 template <class Type> Array<Type>::Array (Type* data, int length) { 00102 n = length; 00103 owner = false; 00104 elems = data; 00105 } 00106 00107 template <class Type> Array<Type>::Array (const Array<Type>& source) { 00108 n = source.n; 00109 owner = false; 00110 elems = source.elems; 00111 } 00112 00113 template <class Type> Array<Type>::~Array () { 00114 if (owner && elems) 00115 delete[] elems; 00116 } 00117 00118 template <class Type> void Array<Type>::setvalue (const Type& value) { 00119 for (int i = 0; i < n; i++) 00120 elems[i] = value; 00121 } 00122 00123 template <class Type> void Array<Type>::inject (const Type* source) { 00124 00125 // Check for self-assignment. If there is self-assignment, there 00126 // is no need to copy because the objects share the same data! 00127 if (elems != source) 00128 copymemory<Type>(source,elems,n); 00129 } 00130 00131 template <class Type> void Array<Type>::inject (const Array<Type>& source) { 00132 if (n != source.n) 00133 throw MatlabException("Unable to perform copy; arrays have \ 00134 different lengths"); 00135 inject(source.elems); 00136 } 00137 00138 template <class Type> Array<Type>& Array<Type>::operator= 00139 (const Type* source) { 00140 inject(source); 00141 return *this; 00142 } 00143 00144 template <class Type> Array<Type>& Array<Type>::operator= 00145 (const Array<Type>& source) { 00146 inject(source); 00147 return *this; 00148 } 00149 00150 template <class Type> void Array<Type>::copyto (Type* dest) const { 00151 Array destarray(dest,n); 00152 destarray.inject(*this); 00153 } 00154 00155 template <class Type> Type& Array<Type>::operator[] (int i) { 00156 return elems[i]; 00157 } 00158 00159 template <class Type> const Type& Array<Type>::operator[] (int i) const { 00160 return elems[i]; 00161 } 00162 00163 #endif