00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef MECHSYS_LINALG_MATRIX_H
00028 #define MECHSYS_LINALG_MATRIX_H
00029
00030 #ifndef ZERO
00031 #define ZERO 1.0e-10
00032 #endif
00033
00034 #include <sstream>
00035 #include <cassert>
00036 #include <cmath>
00037
00038 #include "util/numstreams.h"
00039
00040 using Util::_8s;
00041
00042 namespace LinAlg
00043 {
00044
00045
00046 template <class t_exp, class t_res>
00047 class expression;
00048
00049 template<typename Type>
00050 class Matrix
00051 {
00052 public:
00053
00054 Matrix() : _rows(0), _cols(0), _values(NULL) {}
00055
00056 Matrix(int Rows, int Cols) : _values(NULL) { _set(Rows,Cols); }
00057 Matrix(int Rows, int Cols, std::string const & strVals) : _values(NULL) { _set(Rows,Cols,strVals); }
00058 Matrix(int N, std::string const & strDiagonal, std::string const & strUpperTriang) : _values(NULL) { _set_sym(N,strDiagonal,strUpperTriang); }
00059
00060 ~Matrix()
00061 {
00062 if (_values!=NULL) delete [] _values;
00063 }
00064
00065 Matrix(Matrix<Type> const & Other)
00066 {
00067 _rows = Other.Rows();
00068 _cols = Other.Cols();
00069 _values = new Type [_rows*_cols];
00070 for (int i=0; i<_rows*_cols; ++i)
00071 _values[i] = Other._values[i];
00072 }
00073
00074 int Rows() const { assert(_values!=NULL); return _rows; }
00075 int Cols() const { assert(_values!=NULL); return _cols; }
00076 Type * GetPtr() { assert(_values!=NULL); return _values; }
00077 const Type * GetPtr() const { assert(_values!=NULL); return _values; }
00078 Type Det() const;
00079 void Inv(Matrix<Type> & inv) const;
00080 void Trn(Matrix<Type> & trn) const;
00081
00082 void Set(int Rows, int Cols) { _set(Rows,Cols); }
00083 void Set(int Rows, int Cols, std::string const & strVals) { _set(Rows,Cols,strVals); }
00084 void Set(int N, std::string const & strDiagonal, std::string const & strUpperTriang) { _set_sym(N,strDiagonal,strUpperTriang); }
00085 void SetValues(Type Value)
00086 {
00087 assert(_values!=NULL);
00088 for (int i=0; i<_rows*_cols; ++i)
00089 _values[i] = Value;
00090 }
00091 void Reset(std::string const & strVals)
00092 {
00093 std::istringstream iss(strVals);
00094 for (int i=0; i<_rows; ++i)
00095 for (int j=0; j<_cols; ++j)
00096 iss >> _values[j*_rows+i];
00097 }
00098 void Resize(int Rows, int Cols) { _resize(Rows,Cols); }
00099
00100 void operator= (const Matrix<Type> & R)
00101 {
00102 assert(&R!=this);
00103 if (R.Rows() != _rows || R.Cols() != _cols)
00104 {
00105 _rows = R.Rows();
00106 _cols = R.Cols();
00107 if (_values != NULL) delete [] _values;
00108 _values = new Type [_rows*_cols];
00109 }
00110
00111 int _components=_rows*_cols;
00112 for (int i=0; i<_components; ++i)
00113 _values[i] = R._values[i];
00114 }
00115
00116
00117 class CommaAssign
00118 {
00119 public:
00120 CommaAssign(Type * Values, int & Rows, int & Cols, Type const & FirstValue):_values(Values),_rows(Rows),_cols(Cols),_index(0)
00121 {
00122 assert(_values!=NULL);
00123 _values[0] = FirstValue;
00124 int _components = _rows*_cols;
00125 for (int i=1; i<_components; ++i)
00126 _values[i] = static_cast<Type>(0);
00127 }
00128 CommaAssign & operator, (Type const & Num)
00129 {
00130 _index++;
00131 assert(_index < _rows*_cols);
00132 _values[_index/_cols + (_index % _cols) * _rows] = Num;
00133 return *this;
00134 }
00135 private:
00136 Type * _values;
00137 int & _rows;
00138 int & _cols;
00139 int _index;
00140 };
00141
00142 CommaAssign operator= (Type const & Num)
00143 {
00144 return CommaAssign(_values, _rows, _cols, Num);
00145 }
00146
00147 void operator+= (const Matrix<Type> & R)
00148 {
00149 assert(_values!=NULL);
00150 assert(R.Rows()==_rows);
00151 assert(R.Cols()==_cols);
00152 int _components=_rows*_cols;
00153 for (int i=0; i<_components; ++i)
00154 _values[i] += R._values[i];
00155 }
00156
00157 void operator-= (const Matrix<Type> & R)
00158 {
00159 assert(_values!=NULL);
00160 assert(R.Rows()==_rows);
00161 assert(R.Cols()==_cols);
00162 int _components=_rows*_cols;
00163 for (int i=0; i<_components; ++i)
00164 _values[i] -= R._values[i];
00165 }
00166
00167
00168 template<typename t_exp>
00169 void operator = (const expression<t_exp, Matrix<Type> > & Exp) { Exp.Apply(*this); }
00170
00171 template<typename t_exp>
00172 void operator += (const expression<t_exp, Matrix<Type> > & Exp) { Exp.Apply_pe(*this); }
00173
00174 template<typename t_exp>
00175 void operator -= (const expression<t_exp, Matrix<Type> > & Exp) { Exp.Apply_me(*this); }
00176
00177 Type & operator() (int i, int j)
00178 {
00179 assert(_values!=NULL);
00180 assert(i>=0 & i<_rows);
00181 assert(j>=0 & j<_cols);
00182 return _values[j*_rows+i];
00183 }
00184 const Type & operator() (int i, int j) const
00185 {
00186 assert(_values!=NULL);
00187 assert(i>=0 & i<_rows);
00188 assert(j>=0 & j<_cols);
00189 return _values[j*_rows+i];
00190 }
00191 private:
00192 int _rows;
00193 int _cols;
00194 Type * _values;
00195 void _set(int Rows, int Cols)
00196 {
00197 assert(_values==NULL);
00198 assert(Rows>0);
00199 assert(Cols>0);
00200 _rows = Rows;
00201 _cols = Cols;
00202 _values = new Type [_rows*_cols];
00203 for (int i=0; i<_rows*_cols; ++i)
00204 _values[i] = static_cast<Type>(0);
00205 }
00206 void _set(int Rows, int Cols, std::string const & strVals)
00207 {
00208 assert(_values==NULL);
00209 assert(Rows>0);
00210 assert(Cols>0);
00211 _rows = Rows;
00212 _cols = Cols;
00213 _values = new Type [_rows*_cols];
00214 std::istringstream iss(strVals);
00215 for (int i=0; i<_rows; ++i)
00216 for (int j=0; j<_cols; ++j)
00217 iss >> _values[j*_rows+i];
00218 }
00219 void _resize(int Rows, int Cols)
00220 {
00221 assert(Rows>0);
00222 assert(Cols>0);
00223 if (Rows==_rows && Cols==_cols && _values!=NULL) return;
00224 if (_values!=NULL) delete [] _values;
00225 _rows = Rows;
00226 _cols = Cols;
00227 _values = new Type [_rows*_cols];
00228 }
00229 void _set_sym(int N, std::string const & strDiagonal, std::string const & strUpperTriang)
00230 {
00231 assert(N>0);
00232 _rows = N;
00233 _cols = N;
00234 _values = new Type [_rows*_cols];
00235 std::stringstream iss_D (strDiagonal);
00236 std::stringstream iss_UT (strUpperTriang);
00237
00238 for (int i=0; i<N; ++i)
00239 iss_D >> _values[i*_rows+i];
00240
00241 for (int i=0; i<N-1; ++i)
00242 for (int j=i+1; j<N; ++j)
00243 {
00244 iss_UT >> _values[j*_rows+i];
00245 _values[i*_rows+j] = _values[j*_rows+i];
00246 }
00247 }
00248
00249 };
00250
00251 template<typename Type>
00252 std::ostream & operator<< (std::ostream & os, const Matrix<Type> & M)
00253 {
00254 os << std:: endl;
00255 for (int i=0; i<M.Rows(); ++i)
00256 {
00257 for (int j=0; j<M.Cols(); ++j)
00258 os << _8s()<< M(i,j);
00259 os << std::endl;
00260 }
00261 return os;
00262 }
00263
00264
00265 template<typename Type>
00266 inline Type Matrix<Type>::Det() const
00267 {
00268 Matrix<Type> const & M = (*this);
00269 Type _det;
00270 if (_rows==1)
00271 {
00272 _det = 0;
00273 for (int i=0; i<_cols; i++) _det += pow(M(0,i),2);
00274 _det = pow(_det, 0.5);
00275 }
00276 else if (_rows==3 && _cols==3)
00277 {
00278 _det = M(0,0)*(M(1,1)*M(2,2) - M(1,2)*M(2,1)) \
00279 - M(0,1)*(M(1,0)*M(2,2) - M(1,2)*M(2,0)) \
00280 + M(0,2)*(M(1,0)*M(2,1) - M(1,1)*M(2,0));
00281 }
00282 else if (_rows==2 && _cols==3)
00283 {
00284 Type d1 = M(0,0)*M(1,1) - M(0,1)*M(1,0);
00285 Type d2 = M(0,1)*M(1,2) - M(0,2)*M(1,1);
00286 Type d3 = M(0,2)*M(1,0) - M(0,0)*M(1,2);
00287 _det = sqrt(d1*d1 + d2*d2 + d3*d3);
00288 }
00289 else
00290 {
00291 std::ostringstream oss;
00292 oss << "Matrix::Det: Determinant for a (" << _rows << " x " << _cols << ") matrix is not available\n";
00293 throw oss.str().c_str();
00294 }
00295 return _det;
00296 }
00297
00298 template<typename Type>
00299 inline void Matrix<Type>::Inv(Matrix<Type> & inv) const
00300 {
00301 inv.Resize(_rows, _cols);
00302 Matrix<Type> const & M = (*this);
00303 if (_rows==3 && _cols==3)
00304 {
00305 inv.Resize(3,3);
00306 Type det = Det();
00307 if (fabs(det)<ZERO)
00308 throw "Matrix::Inv: Could not calculate inverse because determinant is equal to zero\n";
00309
00310 inv(0,0) = (M(1,1)*M(2,2) - M(1,2)*M(2,1)) / det;
00311 inv(0,1) = (M(0,2)*M(2,1) - M(0,1)*M(2,2)) / det;
00312 inv(0,2) = (M(0,1)*M(1,2) - M(0,2)*M(1,1)) / det;
00313
00314 inv(1,0) = (M(1,2)*M(2,0) - M(1,0)*M(2,2)) / det;
00315 inv(1,1) = (M(0,0)*M(2,2) - M(0,2)*M(2,0)) / det;
00316 inv(1,2) = (M(0,2)*M(1,0) - M(0,0)*M(1,2)) / det;
00317
00318 inv(2,0) = (M(1,0)*M(2,1) - M(1,1)*M(2,0)) / det;
00319 inv(2,1) = (M(0,1)*M(2,0) - M(0,0)*M(2,1)) / det;
00320 inv(2,2) = (M(0,0)*M(1,1) - M(0,1)*M(1,0)) / det;
00321 }
00322 else
00323 {
00324 inv.Resize(_rows,_cols);
00325 Matrix<Type> extended(_rows, _cols*2);
00326
00327
00328 for (int r = 0; r < _rows; r++)
00329 for (int c = 0; c < _cols; c++)
00330 {
00331 extended(r,c) = this->operator()(r,c);
00332 if (r == c) extended(r,c+_rows) = 1;
00333 else extended(r,c+_rows) = 0;
00334 }
00335
00336 for (int p = 0; p < _cols; p++)
00337 {
00338 for (int r = p + 1; r < _rows; r++)
00339 {
00340
00341 if (fabs(extended(p,p))<1.e-10)
00342 {
00343
00344 int rr;
00345 for (rr = p; rr < _rows; rr++) if (fabs(extended(rr,p)) >= 1.e-10) break;
00346 if (rr==_rows) throw "Matrix::Inv: Error calculating inverse matrix): singular matrix";
00347 for (int c = p; c < _cols*2; c++){
00348 Type temp = extended(p,c);
00349 extended(p,c) = extended(rr,c);
00350 extended(rr,c) = temp;
00351 }
00352 }
00353 Type coef = extended(r,p) / extended(p,p);
00354 for (int c = p; c < _cols*2; c++)
00355 extended(r,c) -= coef * extended(p,c);
00356 }
00357 }
00358
00359
00360 for (int p = _rows-1; p > 0; p--)
00361 {
00362 for (int r = p-1; r >= 0; r--)
00363 {
00364 Type coef = extended(r,p) / extended(p,p);
00365 for (int c = _cols*2-1; c >= p; c--)
00366 extended(r,c) -= coef * extended(p,c);
00367 }
00368 }
00369
00370
00371 for (int r = 0; r < _rows; r++)
00372 for (int c = 0; c < _cols; c++)
00373 inv(r,c) = extended(r,c+_rows) / extended(r,r);
00374
00375 }
00376 }
00377
00378 template<typename Type>
00379 inline void Matrix<Type>::Trn(Matrix<Type> & trn) const
00380 {
00381 trn.Resize(_cols, _rows);
00382 Matrix<Type> const & M = (*this);
00383 for (int r = 0; r < _rows; r++)
00384 for (int c = 0; c < _cols; c++)
00385 trn(c,r) = M(r,c);
00386
00387 }
00388
00389 };
00390
00391 #endif // MECHSYS_LINALG_MATRIX_H
00392
00393