MeshKit
1.0
|
00001 00006 #ifndef __MESHKIT_MATRIXTEMPLATE_H__ 00007 #define __MESHKIT_MATRIXTEMPLATE_H__ 00008 00009 #include <string> 00010 #include <iostream> 00011 #include <fstream> 00012 #include <cassert> 00013 #include <cmath> 00014 #include <stdlib.h> 00015 00016 // defines the Matrix class 00017 template <class T> 00018 class CMatrix 00019 #ifdef __RGGMETER 00020 : public CArrayBase 00021 #endif 00022 { 00023 private: 00024 T **m_pCells; // address where the matrix of 00025 // type T is stored 00026 int m_nRows; // number of rows in the matrix 00027 int m_nColumns; // number of columns in the matrix 00028 std::string m_szName; // matrix name 00029 void ErrorHandler (int,int nR=0, int nC=0) const; 00030 // handles error conditions 00031 void Release (); // similar to destructor 00032 00033 public: 00034 CMatrix (); // default constructor 00035 CMatrix (int, int); // constructor 00036 CMatrix (const char *); // constructor 00037 CMatrix (const char *, int, int); // constructor 00038 CMatrix (const CMatrix<T>&); // copy constructor 00039 ~CMatrix (); // destructor 00040 void SetSize (int, int); // sets the size of the matrix 00041 // used with the default constructor 00042 00043 // helper functions 00044 int GetRows () const; // gets the current number of rows 00045 int GetColumns () const; // gets the current number of columns 00046 void GetName (std::string&) const; // gets the matrix name 00047 00048 // matrix manipulations (mutator) 00049 void Set (T); // sets the value of all elements 00050 // of a matrix 00051 void SetName (const std::string&); // sets the matrix name 00052 T& operator() (int, int); // row-col access 00053 const T& operator() (int, int) const; // row-col access 00054 T& operator= (const CMatrix&); // overloaded = operator 00055 int Read (std::ifstream& IFile); 00056 }; 00057 00058 // =============== definitions =========================================== 00059 template <class T> 00060 CMatrix<T>::CMatrix () 00061 // --------------------------------------------------------------------------- 00062 // Function: default ctor 00063 // Input: none 00064 // Output: none 00065 // --------------------------------------------------------------------------- 00066 { 00067 m_pCells = NULL; 00068 m_nRows = 0; 00069 m_nColumns = 0; 00070 } 00071 00072 template <class T> 00073 CMatrix<T>::CMatrix (int nR, int nC) 00074 // --------------------------------------------------------------------------- 00075 // Function: overloaded ctor 00076 // Input: # of rows and columns 00077 // Output: none 00078 // --------------------------------------------------------------------------- 00079 { 00080 m_pCells = NULL; 00081 SetSize (nR, nC); 00082 } 00083 00084 template <class T> 00085 CMatrix<T>::CMatrix (const char* szName) 00086 // --------------------------------------------------------------------------- 00087 // Function: overloaded ctor 00088 // Input: matrix name 00089 // Output: none 00090 // --------------------------------------------------------------------------- 00091 { 00092 m_pCells = NULL; 00093 m_szName = szName; 00094 m_nRows = 0; 00095 m_nColumns = 0; 00096 } 00097 00098 template <class T> 00099 CMatrix<T>::CMatrix (const char* szName, int nR, int nC) 00100 // --------------------------------------------------------------------------- 00101 // Function: overloaded ctor 00102 // Input: matrix name, # of rows and columns 00103 // Output: none 00104 // --------------------------------------------------------------------------- 00105 { 00106 m_pCells = NULL; 00107 m_szName = szName; 00108 SetSize (nR, nC); 00109 } 00110 00111 template <class T> 00112 CMatrix<T>::CMatrix (const CMatrix<T>& A) 00113 // --------------------------------------------------------------------------- 00114 // Function: copy ctor 00115 // Input: matrix 00116 // Output: none 00117 // --------------------------------------------------------------------------- 00118 { 00119 m_pCells = NULL; 00120 m_nRows = A.m_nRows; 00121 m_nColumns = A.m_nColumns; 00122 m_szName = A.m_szName; 00123 SetSize (m_nRows, m_nColumns); 00124 for (int i=1; i <= m_nRows; i++) 00125 { 00126 for (int j=1; j <= m_nColumns; j++) 00127 { 00128 m_pCells[i][j] = A.m_pCells[i][j]; 00129 } 00130 } 00131 } 00132 00133 template <class T> 00134 void CMatrix<T>::SetSize (int nR, int nC) 00135 // --------------------------------------------------------------------------- 00136 // Function: dynamically allocates memory 00137 // Input: matrix size (# of rows and columns) 00138 // Output: none 00139 // --------------------------------------------------------------------------- 00140 { 00141 // check whether nR and nC are legal 00142 if (nR <= 0 || nC <= 0) 00143 ErrorHandler (3); 00144 Release (); 00145 int size = nR*nC + 1; 00146 try {m_pCells = new T *[nR + 1];} 00147 catch (std::bad_alloc) {ErrorHandler (1);} 00148 try {m_pCells[0] = new T[size];} 00149 catch (std::bad_alloc) {ErrorHandler (1);} 00150 m_pCells[1] = m_pCells[0]; 00151 for (int i=2; i <= nR; i++) 00152 m_pCells[i] = m_pCells[i-1]+nC; 00153 m_nRows = nR; 00154 m_nColumns = nC; 00155 #ifdef __RGGMETER 00156 m_dAllocated += static_cast<double>(sizeof(T*)*(nR+1)); 00157 m_dAllocated += static_cast<double>(sizeof(T)*size); 00158 #endif 00159 } 00160 00161 template <class T> 00162 CMatrix<T>::~CMatrix () 00163 // --------------------------------------------------------------------------- 00164 // Function: dtor 00165 // Input: none 00166 // Output: none 00167 // --------------------------------------------------------------------------- 00168 { 00169 // deallocate storage 00170 if (m_pCells != NULL) 00171 { 00172 delete [] m_pCells[0]; 00173 m_pCells[0] = NULL; 00174 #ifdef __RGGMETER 00175 m_dDeAllocated += static_cast<double>(sizeof(T*)*(m_nRows+1)); 00176 #endif 00177 } 00178 if (m_pCells != NULL) 00179 { 00180 delete [] m_pCells; 00181 m_pCells = NULL; 00182 #ifdef __RGGMETER 00183 int nSize = m_nRows*m_nColumns+1; 00184 m_dDeAllocated += static_cast<double>(sizeof(T)*nSize); 00185 #endif 00186 } 00187 m_nRows = 0; 00188 m_nColumns = 0; 00189 } 00190 00191 template <class T> 00192 void CMatrix<T>::Release () 00193 // --------------------------------------------------------------------------- 00194 // Function: dynamically deallocates memory 00195 // Input: none 00196 // Output: none 00197 // --------------------------------------------------------------------------- 00198 { 00199 // deallocate storage 00200 if (m_pCells != NULL) 00201 { 00202 delete [] m_pCells[0]; 00203 #ifdef __RGGMETER 00204 m_dDeAllocated += static_cast<double>(sizeof(T*)*(m_nRows+1)); 00205 #endif 00206 } 00207 if (m_pCells != NULL) 00208 { 00209 delete [] m_pCells; 00210 #ifdef __RGGMETER 00211 int nSize = m_nRows*m_nColumns+1; 00212 m_dDeAllocated += static_cast<double>(sizeof(T)*nSize); 00213 #endif 00214 } 00215 m_pCells = NULL; 00216 m_nRows = 0; 00217 m_nColumns = 0; 00218 } 00219 00220 // =============== member functions =========================================== 00221 template <class T> 00222 void CMatrix<T>::SetName (const std::string& szName) 00223 // --------------------------------------------------------------------------- 00224 // Function: sets the name of the matrix 00225 // Input: matrix name 00226 // Output: none 00227 // --------------------------------------------------------------------------- 00228 { 00229 m_szName = szName; 00230 } 00231 00232 template <class T> 00233 void CMatrix<T>::GetName (std::string& szName) const 00234 // --------------------------------------------------------------------------- 00235 // Function: gets the name of the matrix 00236 // Input: string to hold matrix name 00237 // Output: matrix name 00238 // --------------------------------------------------------------------------- 00239 { 00240 szName = m_szName; 00241 } 00242 00243 template <class T> 00244 int CMatrix<T>::GetRows () const 00245 // --------------------------------------------------------------------------- 00246 // Function: gets the # of rows in the matrix 00247 // Input: none 00248 // Output: # of rows 00249 // --------------------------------------------------------------------------- 00250 { 00251 return (m_nRows); 00252 } 00253 00254 template <class T> 00255 int CMatrix<T>::GetColumns () const 00256 // --------------------------------------------------------------------------- 00257 // Function: gets the # of columns in the matrix 00258 // Input: none 00259 // Output: # of columns 00260 // --------------------------------------------------------------------------- 00261 { 00262 return (m_nColumns); 00263 } 00264 00265 template <class T> 00266 void CMatrix<T>::Set (T dV) 00267 // --------------------------------------------------------------------------- 00268 // Function: sets the value of all the elements in the matrix to the 00269 // specified value 00270 // Input: specified value 00271 // Output: none 00272 // --------------------------------------------------------------------------- 00273 { 00274 for (int i=1; i <= m_nRows; i++) 00275 { 00276 for (int j=1; j <= m_nColumns; j++) 00277 { 00278 m_pCells[i][j] = dV; // or, (*this)(i,j) = dV; 00279 } 00280 } 00281 } 00282 00283 // ==================== Overloaded Operators ======================== 00284 template <class T> 00285 T& CMatrix<T>::operator() (int nR, int nC) 00286 // --------------------------------------------------------------------------- 00287 // Function: overloaded () operator to access matrix contents 00288 // carries out bound checking 00289 // Input: row and column indices 00290 // Output: value at the specified indices 00291 // --------------------------------------------------------------------------- 00292 { 00293 #ifdef _DEBUG 00294 if (nR <= 0 || nR > m_nRows || nC <= 0 || nC > m_nColumns) 00295 { 00296 ErrorHandler (2,nR,nC); 00297 return m_pCells[1][1]; 00298 } 00299 else 00300 return m_pCells[nR][nC]; 00301 #else 00302 return m_pCells[nR][nC]; 00303 #endif 00304 } 00305 00306 template <class T> 00307 const T& CMatrix<T>::operator() (int nR, int nC) const 00308 // --------------------------------------------------------------------------- 00309 // Function: overloaded () operator to access matrix contents 00310 // carries out bound checking 00311 // Input: row and column indices 00312 // Output: value at the specified indices 00313 // --------------------------------------------------------------------------- 00314 { 00315 #ifdef _DEBUG 00316 if (nR <= 0 || nR > m_nRows || nC <= 0 || nC > m_nColumns) 00317 { 00318 ErrorHandler (2,nR,nC); 00319 return m_pCells[1][1]; 00320 } 00321 else 00322 return m_pCells[nR][nC]; 00323 #else 00324 return m_pCells[nR][nC]; 00325 #endif 00326 } 00327 00328 template <class T> 00329 T& CMatrix<T>::operator= (const CMatrix& matarg) 00330 // --------------------------------------------------------------------------- 00331 // Function: overloaded = operator 00332 // Input: matrix to use as rvalue 00333 // Output: modified values 00334 // --------------------------------------------------------------------------- 00335 { 00336 // check whether matrix is assigned to itself 00337 if (this != &matarg) 00338 { 00339 // compatible matrices? 00340 if (m_nRows != matarg.m_nRows || m_nColumns != matarg.m_nColumns) 00341 { 00342 ErrorHandler (4); 00343 return (T&)(*this); 00344 } 00345 // now copy 00346 for (int i=1; i <= matarg.m_nRows; i++) 00347 { 00348 for (int j=1; j <= matarg.m_nColumns; j++) 00349 { 00350 m_pCells[i][j]= matarg.m_pCells[i][j]; 00351 } 00352 } 00353 } 00354 00355 return (T&)(*this); 00356 } 00357 00358 template <class T> 00359 int CMatrix<T>::Read (std::ifstream& IFile) 00360 // --------------------------------------------------------------------------- 00361 // Function: Reads a matrix rowwise 00362 // Input: input stream to read from 00363 // Output: the modified matrix 00364 // --------------------------------------------------------------------------- 00365 { 00366 // read matrix size 00367 int m_nRowsI, nColsI; 00368 IFile >> m_nRowsI >> nColsI; 00369 if (m_nRowsI <= 0 || nColsI <= 0) 00370 return 1; 00371 if (IFile.eof() || IFile.fail()) 00372 return 1; 00373 00374 // reallocate? 00375 if (m_nRows != m_nRowsI || m_nColumns != nColsI) 00376 SetSize (m_nRowsI, nColsI); 00377 00378 T v; 00379 00380 for (int i=1; i <= m_nRows; i++) 00381 { 00382 for (int j=1; j <= m_nColumns; j++) 00383 { 00384 IFile >> v; 00385 m_pCells[i][j] = v; 00386 if (IFile.eof() || IFile.fail()) 00387 return 1; 00388 } 00389 } 00390 00391 return 0; 00392 } 00393 00394 // ==================== Error Handler ======================== 00395 template <class T> 00396 void CMatrix<T>::ErrorHandler (int nErrorCode, int nR, int nC) const 00397 // --------------------------------------------------------------------------- 00398 // Function: channels error message via std:err 00399 // Input: error code and optional int value 00400 // Output: none 00401 // --------------------------------------------------------------------------- 00402 { 00403 std::cerr << "CMatrix: Matrix Name: " << m_szName << ".\n"; 00404 switch (nErrorCode) 00405 { 00406 case 1: 00407 std::cerr << "Matrix:: Memory allocation failure.\n"; 00408 break; 00409 case 2: 00410 std::cerr << "Matrix::Row-Column reference is out of bounds.\n"; 00411 break; 00412 case 3: 00413 std::cerr << "Matrix::Constructor. Invalid number of rows " 00414 "or columns.\n"; 00415 break; 00416 case 4: 00417 std::cerr << "Matrix::Incompatible matrices.\n"; 00418 break; 00419 } 00420 std::cerr << "Unable to populate matrix.\n"; 00421 exit (1); 00422 } 00423 00424 #endif