![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raúl D. D. Farfan * 00004 * * 00005 * This program is free software: you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation, either version 3 of the License, or * 00008 * any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00017 ************************************************************************/ 00018 00019 #ifndef MECHSYS_LINALG_MATRIX_H 00020 #define MECHSYS_LINALG_MATRIX_H 00021 00022 // STL 00023 #include <iostream> 00024 #include <cmath> 00025 00026 // MechSys 00027 #include <mechsys/util/fatal.h> 00028 00029 extern "C" 00030 { 00031 // BLAS 00032 void dscal_(int const *N, double const *alpha, double *X, int const *incX); 00033 void dcopy_(int const *N, double const *X, int const *incX, double *Y, int const *incY); 00034 void daxpy_(int const *N, double const *alpha, double const *X, int const *incX, double *Y, int const *incY); 00035 } 00036 00037 namespace LinAlg 00038 { 00039 00040 // Prototype for expression classes 00041 template <class t_exp, class t_res> 00042 class expression; // should not be called (directly) by the user 00043 00056 template<typename Value_T> 00057 class Matrix 00058 { 00059 public: 00060 // Constructors 00061 Matrix () : _rows(0), _cols(0), _values(NULL), data(_values) {} 00062 Matrix (int Rows, int Cols); 00063 Matrix (Matrix<Value_T> const & Other); 00064 00066 ~Matrix () { if (_values!=NULL) delete [] _values; } 00067 00068 // Access methods 00069 int Rows () const; 00070 int Cols () const; 00071 size_t num_rows () const { return (size_t)Rows(); } 00072 size_t num_cols () const { return (size_t)Cols(); } 00073 Value_T const * GetPtr () const; 00074 Value_T * GetPtr (); 00075 00076 // Methods 00077 void Resize (int Rows, int Cols); 00078 void change_dim (int Rows, int Cols) { Resize(Rows,Cols); } 00079 void SetValues (Value_T Value); 00080 00081 // Operators 00082 void operator= (Matrix<Value_T> const & R); 00083 void operator+= (Matrix<Value_T> const & R); 00084 void operator-= (Matrix<Value_T> const & R); 00085 void operator/= (Value_T const & Scalar); 00086 void operator*= (Value_T const & Scalar); 00087 Value_T & operator() (int i, int j); 00088 const Value_T & operator() (int i, int j) const; 00089 00090 // Auxiliar structures 00091 // operator to assign values separated by commas \cond 00092 class CommaAssign 00093 { 00094 public: 00095 CommaAssign(Value_T * Values, int & Rows, int & Cols, Value_T const & FirstValue):_values(Values),_rows(Rows),_cols(Cols),_index(0) 00096 { 00097 if (_values==NULL) throw new Fatal("Matrix::CommaAssign::CommaAssign (_values==NULL). The matrix must be resized prior to use this method."); 00098 _values[0] = FirstValue; 00099 int _components = _rows*_cols; 00100 for (int i=1; i<_components; ++i) 00101 _values[i] = static_cast<Value_T>(0); 00102 } 00103 CommaAssign & operator, (Value_T const & Num) 00104 { 00105 _index++; 00106 if (_index>=_rows*_cols) throw new Fatal("Matrix::CommaAssign::operator, (_index>=_rows*_cols). There are too many values in the comma expression to be assigned to this matrix."); 00107 _values[_index/_cols + (_index % _cols) * _rows] = Num; // considering col major 00108 return *this; 00109 } 00110 private: 00111 Value_T * _values; 00112 int & _rows; 00113 int & _cols; 00114 int _index; 00115 }; 00116 00117 CommaAssign operator= (Value_T const & Num) 00118 { 00119 return CommaAssign(_values, _rows, _cols, Num); 00120 } 00121 00122 // Methods required by the expressions evaluation 00123 template<typename t_exp> 00124 void operator= (const expression<t_exp, Matrix<Value_T> > & Exp) { Exp.Apply(*this); } 00125 00126 template<typename t_exp> 00127 void operator+= (const expression<t_exp, Matrix<Value_T> > & Exp) { Exp.Apply_pe(*this); } 00128 00129 template<typename t_exp> 00130 void operator-= (const expression<t_exp, Matrix<Value_T> > & Exp) { Exp.Apply_me(*this); } 00131 // \endcond 00132 00133 private: 00134 // Data 00135 int _rows; 00136 int _cols; 00137 Value_T * _values; 00138 00139 public: 00140 Value_T * data; 00141 00142 }; // class Matrix 00143 00144 00146 00147 00148 // Constructors 00149 00150 template<typename Value_T> 00151 inline Matrix<Value_T>::Matrix(int Rows, int Cols) 00152 : _rows(0), _cols(0), _values(NULL), data(_values) 00153 { 00154 if (Rows>0 && Cols>0) 00155 { 00156 _rows = Rows; 00157 _cols = Cols; 00158 _values = new Value_T [_rows*_cols]; 00159 for (int i=0; i<_rows*_cols; ++i) 00160 _values[i] = static_cast<Value_T>(0); 00161 data = _values; 00162 } 00163 } 00164 00165 template<typename Value_T> 00166 inline Matrix<Value_T>::Matrix(Matrix<Value_T> const & R) 00167 : _rows(R.Rows()), _cols(R.Cols()), _values(NULL), data(_values) 00168 { 00169 if (_rows>0 && _cols>0) 00170 { 00171 // allocate memory 00172 _values = new Value_T [_rows*_cols]; 00173 data = _values; 00174 00175 // copy 00176 int n = _rows*_cols; 00177 int i = 1; 00178 int j = 1; 00179 dcopy_ (&n, R.GetPtr(), &i, _values, &j); 00180 } 00181 } 00182 00183 // Access methods 00184 00185 template<typename Value_T> 00186 inline int Matrix<Value_T>::Rows() const 00187 { 00188 return _rows; 00189 } 00190 00191 template<typename Value_T> 00192 inline int Matrix<Value_T>::Cols() const 00193 { 00194 return _cols; 00195 } 00196 00197 template<typename Value_T> 00198 inline Value_T * Matrix<Value_T>::GetPtr() 00199 { 00200 #ifndef DNDEBUG 00201 //if (_values==NULL) throw new Fatal("Matrix::GetPtr: (_values==NULL). The matrix must be resized prior to get a pointer to its values."); 00202 #endif 00203 return _values; 00204 } 00205 00206 template<typename Value_T> 00207 inline const Value_T * Matrix<Value_T>::GetPtr() const 00208 { 00209 #ifndef DNDEBUG 00210 //if (_values==NULL) throw new Fatal("Matrix::GetPtr: (_values==NULL). The matrix must be resized prior to get a pointer to its values."); 00211 #endif 00212 return _values; 00213 } 00214 00215 // Methods 00216 00217 template<typename Value_T> 00218 inline void Matrix<Value_T>::Resize(int Rows, int Cols) 00219 { 00220 if (Rows>0 && Cols>0) 00221 { 00222 if (Rows==_rows && Cols==_cols && _values!=NULL) return; 00223 if (_values!=NULL) delete [] _values; 00224 _rows = Rows; 00225 _cols = Cols; 00226 _values = new Value_T [_rows*_cols]; 00227 data = _values; 00228 for (int i=0; i<_rows*_cols; ++i) _values[i] = static_cast<Value_T>(0); 00229 } 00230 else 00231 { 00232 if (_values!=NULL) delete [] _values; 00233 _rows = 0; 00234 _cols = 0; 00235 _values = NULL; 00236 data = _values; 00237 } 00238 } 00239 00240 template<typename Value_T> 00241 inline void Matrix<Value_T>::SetValues(Value_T Value) 00242 { 00243 #ifndef DNDEBUG 00244 if (_values==NULL) throw new Fatal("Matrix::SetValues: (_values==NULL). The matrix must be resized prior to set its values."); 00245 #endif 00246 for (int i=0; i<_rows*_cols; ++i) 00247 _values[i] = Value; 00248 } 00249 00250 // Operators 00251 00252 template<typename Value_T> 00253 inline void Matrix<Value_T>::operator= (Matrix<Value_T> const & R) 00254 { 00255 #ifndef DNDEBUG 00256 if (&R==this) throw new Fatal("Matrix::operator= The right-hand-size of this operation (LHS = RHS) must not be equal to the LHS."); 00257 #endif 00258 00259 // reallocate if they are different (LHS != RHS) 00260 if (_values==NULL || R.Rows()!=_rows || R.Cols()!=_cols) 00261 { 00262 _rows = R.Rows(); 00263 _cols = R.Cols(); 00264 if (_values!=NULL) delete [] _values; 00265 _values = new Value_T [_rows*_cols]; 00266 data = _values; 00267 } 00268 00269 // copy 00270 int n = _rows*_cols; 00271 int i = 1; 00272 int j = 1; 00273 dcopy_ (&n, R.GetPtr(), &i, _values, &j); 00274 } 00275 00276 template<typename Value_T> 00277 inline void Matrix<Value_T>::operator+= (Matrix<Value_T> const & R) 00278 { 00279 #ifndef DNDEBUG 00280 if (_values==NULL ) return;//throw new Fatal("Matrix::operator+= (_values==NULL). The matrix must be resized prior to use this method."); 00281 if (R.Rows()!=_rows) throw new Fatal("Matrix::operator+= (R.Rows()!=_rows). The number of Rows of the LHS (%d) must be equal to the number of rows of the RHS (%d).",R.Rows(),_rows); 00282 if (R.Cols()!=_cols) throw new Fatal("Matrix::operator+= (R.Rows()!=_cols). The number of Cols of the LHS (%d) must be equal to the number of cols of the RHS (%d).",R.Cols(),_cols); 00283 #endif 00284 int n = _rows*_cols; 00285 Value_T a = 1.0; 00286 int i = 1; 00287 int j = 1; 00288 daxpy_ (&n, &a, R.GetPtr(), &i, _values, &j); 00289 } 00290 00291 template<typename Value_T> 00292 inline void Matrix<Value_T>::operator-= (Matrix<Value_T> const & R) 00293 { 00294 #ifndef DNDEBUG 00295 if (_values==NULL ) return;//throw new Fatal("Matrix::operator-= (_values==NULL). The matrix must be resized prior to use this method."); 00296 if (R.Rows()!=_rows) throw new Fatal("Matrix::operator-= (R.Rows()!=_rows). The number of Rows of the LHS (%d) must be equal to the number of rows of the RHS (%d).",R.Rows(),_rows); 00297 if (R.Cols()!=_cols) throw new Fatal("Matrix::operator-= (R.Rows()!=_cols). The number of Cols of the LHS (%d) must be equal to the number of cols of the RHS (%d).",R.Cols(),_cols); 00298 #endif 00299 int n = _rows*_cols; 00300 Value_T a = -1.0; 00301 int i = 1; 00302 int j = 1; 00303 daxpy_ (&n, &a, R.GetPtr(), &i, _values, &j); 00304 } 00305 00306 template<typename Value_T> 00307 inline void Matrix<Value_T>::operator/= (Value_T const & Scalar) 00308 { 00309 #ifndef DNDEBUG 00310 if (_values==NULL) return;//throw new Fatal("Matrix::operator/= (_values==NULL). The matrix must be resized before calling this method."); 00311 #endif 00312 int n = _rows*_cols; 00313 Value_T a = 1.0/Scalar; 00314 int d = 1; 00315 dscal_ (&n, &a, _values, &d); 00316 } 00317 00318 template<typename Value_T> 00319 inline void Matrix<Value_T>::operator*= (Value_T const & Scalar) 00320 { 00321 #ifndef DNDEBUG 00322 if (_values==NULL) return;//throw new Fatal("Matrix::operator*= (_values==NULL). The matrix must be resized before calling this method."); 00323 #endif 00324 int n = _rows*_cols; 00325 Value_T a = Scalar; 00326 int d = 1; 00327 dscal_ (&n, &a, _values, &d); 00328 } 00329 00330 template<typename Value_T> 00331 inline Value_T & Matrix<Value_T>::operator() (int i, int j) 00332 { 00333 #ifndef DNDEBUG 00334 if (_values==NULL ) throw new Fatal("Matrix::operator() (_values==NULL). The matrix must be resized prior to use this method."); 00335 if (i<0 || i>=_rows) throw new Fatal("Matrix::operator() (i<0 || i>=_rows). The index (i=%d) for a row must be greater than/or equal to zero and smaller than the number of rows (nrow=%d).",i,_rows); 00336 if (j<0 || j>=_cols) throw new Fatal("Matrix::operator() (j<0 || j>=_cols). The index (j=%d) for a column must be greater than/or equal to zero and smaller than the number of columns (ncol=%d).",j,_cols); 00337 #endif 00338 return _values[j*_rows+i]; // Col major 00339 } 00340 00341 template<typename Value_T> 00342 inline const Value_T & Matrix<Value_T>::operator() (int i, int j) const 00343 { 00344 #ifndef DNDEBUG 00345 if (_values==NULL ) throw new Fatal("Matrix::(const)operator() (_values==NULL). The matrix must be resized prior to use this method."); 00346 if (i<0 || i>=_rows) throw new Fatal("Matrix::(const)operator() (i<0 || i>=_rows). The index (i=%d) for a row must be greater than/or equal to zero and smaller than the number of rows (nrow=%d).",i,_rows); 00347 if (j<0 || j>=_cols) throw new Fatal("Matrix::(const)operator() (j<0 || j>=_cols). The index (j=%d) for a column must be greater than/or equal to zero and smaller than the number of columns (ncol=%d).",j,_cols); 00348 #endif 00349 return _values[j*_rows+i]; // Col major 00350 } 00351 00353 template<typename Value_T> 00354 std::ostream & operator<< (std::ostream & os, const Matrix<Value_T> & M) 00355 { 00356 for (int i=0; i<M.Rows(); ++i) 00357 { 00358 for (int j=0; j<M.Cols(); ++j) os << M(i,j) << " "; 00359 os << std::endl; 00360 } 00361 return os; 00362 } 00363 00364 00365 }; // namespace LinAlg 00366 00367 #endif // MECHSYS_LINALG_MATRIX_H