00001
00002
00003
00004
00005
00006
00007
00008 #ifndef DENSEMATRIX_HH
00009 #define DENSEMATRIX_HH
00010
00011 #include <iostream>
00012 #include <fstream>
00013 #include <sstream>
00014 #include <string>
00015 #include <iomanip>
00016 #include <cstdlib>
00017 #include "vector.hh"
00018
00019
00020 namespace hdnum {
00021
00025 template<typename REAL>
00026 class DenseMatrix
00027 {
00028 public:
00030 typedef std::size_t size_type;
00031 typedef typename std::vector<REAL> VType;
00032 typedef typename VType::const_iterator ConstVectorIterator;
00033 typedef typename VType::iterator VectorIterator;
00034
00035 private:
00036 VType m_data;
00037 std::size_t m_rows;
00038 std::size_t m_cols;
00039
00040 static bool bScientific;
00041 static std::size_t nIndexWidth;
00042 static std::size_t nValueWidth;
00043 static std::size_t nValuePrecision;
00044
00045
00046
00047 REAL myabs (REAL x) const
00048 {
00049 if (x>=REAL(0))
00050 return x;
00051 else
00052 return -x;
00053 }
00054
00055
00056
00057 inline REAL & at(const std::size_t row, const std::size_t col)
00058 {
00059 return m_data[row * m_cols + col];
00060 }
00061
00062
00063 inline const REAL & at(const std::size_t row, const std::size_t col) const
00064 {
00065 return m_data[row * m_cols + col];
00066 }
00067
00068
00069
00070
00071
00072 public:
00073
00074
00075 DenseMatrix()
00076 : m_data( 0, 0 )
00077 , m_rows( 0 )
00078 , m_cols( 0 )
00079 {
00080 }
00081
00082
00083 DenseMatrix( const std::size_t _rows,
00084 const std::size_t _cols,
00085 const REAL def_val=0
00086 )
00087 : m_data( _rows*_cols, def_val )
00088 , m_rows( _rows )
00089 , m_cols( _cols )
00090 {
00091 }
00092
00093 void addNewRow( const hdnum::Vector<REAL> & rowvector ){
00094 m_rows++;
00095 m_cols = rowvector.size();
00096 for(std::size_t i=0; i<m_cols; i++ )
00097 m_data.push_back( rowvector[i] );
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00125 size_t rowsize () const
00126 {
00127 return m_rows;
00128 }
00129
00145 size_t colsize () const
00146 {
00147 return m_cols;
00148 }
00149
00150
00151
00152 bool scientific() const
00153 {
00154 return bScientific;
00155 }
00156
00180 void scientific(bool b) const
00181 {
00182 bScientific=b;
00183 }
00184
00186 std::size_t iwidth () const
00187 {
00188 return nIndexWidth;
00189 }
00190
00192 std::size_t width () const
00193 {
00194 return nValueWidth;
00195 }
00196
00198 std::size_t precision () const
00199 {
00200 return nValuePrecision;
00201 }
00202
00204 void iwidth (std::size_t i) const
00205 {
00206 nIndexWidth=i;
00207 }
00208
00210 void width (std::size_t i) const
00211 {
00212 nValueWidth=i;
00213 }
00214
00216 void precision (std::size_t i) const
00217 {
00218 nValuePrecision=i;
00219 }
00220
00221
00266
00267
00268 inline REAL & operator()(const std::size_t row, const std::size_t col)
00269 {
00270 assert(row < m_rows|| col < m_cols);
00271 return at(row,col);
00272 }
00273
00274
00275 inline const REAL & operator()(const std::size_t row, const std::size_t col) const
00276 {
00277 assert(row < m_rows|| col < m_cols);
00278 return at(row,col);
00279 }
00280
00281
00282
00283 const ConstVectorIterator operator[](const std::size_t row) const
00284 {
00285 assert(row < m_rows);
00286 return m_data.begin() + row * m_cols;
00287 }
00288
00333
00334 VectorIterator operator[](const std::size_t row)
00335 {
00336 assert(row < m_rows);
00337 return m_data.begin() + row * m_cols;
00338 }
00339
00340
00341
00364 DenseMatrix& operator= (const DenseMatrix& A)
00365 {
00366 m_data = A.m_data;
00367 m_rows = A.m_rows;
00368 m_cols = A.m_cols;
00369 return *this;
00370 }
00371
00372
00373
00395 DenseMatrix& operator= (const REAL& value)
00396 {
00397 for (std::size_t i=0; i<rowsize(); i++)
00398 for (std::size_t j=0; j<colsize(); j++)
00399 (*this)(i,j) = value;
00400 return *this;
00401 }
00402
00403
00404
00405
00406
00407
00408
00416 DenseMatrix& operator+= (const DenseMatrix& B)
00417 {
00418 for (std::size_t i=0; i<rowsize(); ++i)
00419 for (std::size_t j=0; j<colsize(); ++j)
00420 (*this)(i,j) += B(i,j);
00421 return *this;
00422 }
00423
00431 DenseMatrix& operator-= (const DenseMatrix& B)
00432 {
00433 for (std::size_t i=0; i<rowsize(); ++i)
00434 for (std::size_t j=0; j<colsize(); ++j)
00435 (*this)(i,j) -= B(i,j);
00436 return *this;
00437 }
00438
00439
00469 DenseMatrix& operator*= (const REAL& s)
00470 {
00471 for (std::size_t i=0; i<rowsize(); ++i)
00472 for (std::size_t j=0; j<colsize(); ++j)
00473 (*this)(i,j) *= s;
00474 return *this;
00475 }
00476
00477
00508 DenseMatrix& operator/= (const REAL& s)
00509 {
00510 for (std::size_t i=0; i<rowsize(); ++i)
00511 for (std::size_t j=0; j<colsize(); ++j)
00512 (*this)(i,j) /= s;
00513 return *this;
00514 }
00515
00516
00543 void update (const REAL& s, const DenseMatrix& B)
00544 {
00545 for (std::size_t i=0; i<rowsize(); ++i)
00546 for (std::size_t j=0; j<colsize(); ++j)
00547 (*this)(i,j) += s*B(i,j);
00548 }
00549
00550
00551
00593 template<class V>
00594 void mv (Vector<V>& y, const Vector<V>& x) const
00595 {
00596 if (this->rowsize()!=y.size())
00597 HDNUM_ERROR("mv: size of A and y do not match");
00598 if (this->colsize()!=x.size())
00599 HDNUM_ERROR("mv: size of A and x do not match");
00600 for (std::size_t i=0; i<rowsize(); ++i)
00601 {
00602 y[i] = 0;
00603 for (std::size_t j=0; j<colsize(); ++j)
00604 y[i] += (*this)(i,j)*x[j];
00605 }
00606 }
00607
00608
00655 template<class V>
00656 void umv (Vector<V>& y, const Vector<V>& x) const
00657 {
00658 if (this->rowsize()!=y.size())
00659 HDNUM_ERROR("mv: size of A and y do not match");
00660 if (this->colsize()!=x.size())
00661 HDNUM_ERROR("mv: size of A and x do not match");
00662 for (std::size_t i=0; i<rowsize(); ++i)
00663 {
00664 for (std::size_t j=0; j<colsize(); ++j)
00665 y[i] += (*this)(i,j)*x[j];
00666 }
00667 }
00668
00669
00718 template<class V>
00719 void umv (Vector<V>& y, const V& s, const Vector<V>& x) const
00720 {
00721 if (this->rowsize()!=y.size())
00722 HDNUM_ERROR("mv: size of A and y do not match");
00723 if (this->colsize()!=x.size())
00724 HDNUM_ERROR("mv: size of A and x do not match");
00725 for (std::size_t i=0; i<rowsize(); ++i)
00726 {
00727 for (std::size_t j=0; j<colsize(); ++j)
00728 y[i] += s*(*this)(i,j)*x[j];
00729 }
00730 }
00731
00732
00733
00782 void mm (const DenseMatrix<REAL>& A, const DenseMatrix<REAL>& B)
00783 {
00784 if (this->rowsize()!=A.rowsize())
00785 HDNUM_ERROR("mm: size incompatible");
00786 if (this->colsize()!=B.colsize())
00787 HDNUM_ERROR("mm: size incompatible");
00788 if (A.colsize()!=B.rowsize())
00789 HDNUM_ERROR("mm: size incompatible");
00790
00791 for (std::size_t i=0; i<rowsize(); i++)
00792 for (std::size_t j=0; j<colsize(); j++)
00793 {
00794 (*this)(i,j) = 0;
00795 for (std::size_t k=0; k<A.colsize(); k++)
00796 (*this)(i,j) += A(i,k)*B(k,j);
00797 }
00798 }
00799
00800
00855 void umm (const DenseMatrix<REAL>& A, const DenseMatrix<REAL>& B)
00856 {
00857 if (this->rowsize()!=A.rowsize())
00858 HDNUM_ERROR("mm: size incompatible");
00859 if (this->colsize()!=B.colsize())
00860 HDNUM_ERROR("mm: size incompatible");
00861 if (A.colsize()!=B.rowsize())
00862 HDNUM_ERROR("mm: size incompatible");
00863
00864 for (std::size_t i=0; i<rowsize(); i++)
00865 for (std::size_t j=0; j<colsize(); j++)
00866 for (std::size_t k=0; k<A.colsize(); k++)
00867 (*this)(i,j) += A(i,k)*B(k,j);
00868 }
00869
00870
00871
00906 void sc (const Vector<REAL>& x, std::size_t k)
00907 {
00908 if (this->rowsize()!=x.size())
00909 HDNUM_ERROR("cc: size incompatible");
00910
00911 for (std::size_t i=0; i<rowsize(); i++)
00912 (*this)(i,k) = x[i];
00913 }
00914
00951 void sr (const Vector<REAL>& x, std::size_t k)
00952 {
00953 if (this->colsize()!=x.size())
00954 HDNUM_ERROR("cc: size incompatible");
00955
00956 for (std::size_t i=0; i<colsize(); i++)
00957 (*this)(k,i) = x[i];
00958 }
00959
00960
00962 REAL norm_infty () const
00963 {
00964 REAL norm(0.0);
00965 for (std::size_t i=0; i<rowsize(); i++)
00966 {
00967 REAL sum(0.0);
00968 for (std::size_t j=0; j<colsize(); j++)
00969 sum += myabs((*this)(i,j));
00970 if (sum>norm) norm = sum;
00971 }
00972 return norm;
00973 }
00974
00976 REAL norm_1 () const
00977 {
00978 REAL norm(0.0);
00979 for (std::size_t j=0; j<colsize(); j++)
00980 {
00981 REAL sum(0.0);
00982 for (std::size_t i=0; i<rowsize(); i++)
00983 sum += myabs((*this)(i,j));
00984 if (sum>norm) norm = sum;
00985 }
00986 return norm;
00987 }
00988
00989
00990
01037 Vector<REAL> operator* (const Vector<REAL> & x)
01038 {
01039 assert( x.size() == rowsize() );
01040
01041 Vector<REAL> y( rowsize() );
01042 for(std::size_t r=0; r<rowsize(); ++r){
01043 for(std::size_t c=0; c<colsize(); ++c){
01044 y[r]+= at(r,c) * x[c];
01045 }
01046 }
01047 return y;
01048 }
01049
01050
01051
01052
01096 DenseMatrix operator* (const DenseMatrix & x) const
01097 {
01098 assert(colsize() == x.rowsize());
01099
01100 const std::size_t out_rows = rowsize();
01101 const std::size_t out_cols = x.colsize();
01102 DenseMatrix y(out_rows, out_cols,0.0);
01103 for(std::size_t r=0; r<out_rows; ++r)
01104 for(std::size_t c=0; c<out_cols; ++c)
01105 for(std::size_t i=0; i<colsize(); ++i)
01106 y(r,c) += at(r,i) * x(i,c);
01107
01108 return y;
01109 }
01110
01111
01112
01156 DenseMatrix operator+ (const DenseMatrix & x) const
01157 {
01158 assert(colsize() == x.rowsize());
01159
01160 const std::size_t out_rows = rowsize();
01161 const std::size_t out_cols = x.colsize();
01162 DenseMatrix y(out_rows, out_cols,0.0);
01163 y = *this;
01164 y+=x;
01165 return y;
01166 }
01167
01168
01169
01213 DenseMatrix operator- (const DenseMatrix & x) const
01214 {
01215 assert(colsize() == x.rowsize());
01216
01217 const std::size_t out_rows = rowsize();
01218 const std::size_t out_cols = x.colsize();
01219 DenseMatrix y(out_rows, out_cols,0.0);
01220 y = *this;
01221 y-=x;
01222 return y;
01223 }
01224
01225
01226 };
01227
01228
01229
01230 template<typename REAL>
01231 bool DenseMatrix<REAL>::bScientific = true;
01232 template<typename REAL>
01233 std::size_t DenseMatrix<REAL>::nIndexWidth = 10;
01234 template<typename REAL>
01235 std::size_t DenseMatrix<REAL>::nValueWidth = 10;
01236 template<typename REAL>
01237 std::size_t DenseMatrix<REAL>::nValuePrecision = 3;
01238
01239
01263 template <typename REAL>
01264 inline std::ostream& operator<< (std::ostream& s, const DenseMatrix<REAL>& A)
01265 {
01266 s << std::endl;
01267 s << " " << std::setw(A.iwidth()) << " " << " ";
01268 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
01269 s << std::setw(A.width()) << j << " ";
01270 s << std::endl;
01271
01272 for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i)
01273 {
01274 s << " " << std::setw(A.iwidth()) << i << " ";
01275 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
01276 {
01277 if( A.scientific() )
01278 {
01279 s << std::setw(A.width())
01280 << std::scientific
01281 << std::showpoint
01282 << std::setprecision(A.precision())
01283 << A[i][j] << " ";
01284 }
01285 else
01286 {
01287 s << std::setw(A.width())
01288 << std::fixed
01289 << std::showpoint
01290 << std::setprecision(A.precision())
01291 << A[i][j] << " ";
01292 }
01293 }
01294 s << std::endl;
01295 }
01296 return s;
01297 }
01298
01299
01301 template<typename REAL>
01302 inline void zero (DenseMatrix<REAL> &A)
01303 {
01304 for (std::size_t i=0; i<A.rowsize(); ++i)
01305 for (std::size_t j=0; j<A.colsize(); ++j)
01306 A(i,j) = REAL(0);
01307 }
01308
01309
01343 template<class T>
01344 inline void identity (DenseMatrix<T> &A)
01345 {
01346 for (typename DenseMatrix<T>::size_type i=0; i<A.rowsize(); ++i)
01347 for (typename DenseMatrix<T>::size_type j=0; j<A.colsize(); ++j)
01348 if (i==j)
01349 A[i][i] = T(1);
01350 else
01351 A[i][j] = T(0);
01352 }
01353
01389 template<typename REAL>
01390 inline void spd (DenseMatrix<REAL> &A)
01391 {
01392 if (A.rowsize()!=A.colsize() || A.rowsize()==0)
01393 HDNUM_ERROR("need square and nonempty matrix");
01394 for (std::size_t i=0; i<A.rowsize(); ++i)
01395 for (std::size_t j=0; j<A.colsize(); ++j)
01396 if (i==j)
01397 A(i,i) = REAL(4.0);
01398 else
01399 A(i,j) = - REAL(1.0)/((i-j)*(i-j));
01400 }
01401
01451 template<typename REAL>
01452 inline void vandermonde (DenseMatrix<REAL> &A, const Vector<REAL> x)
01453 {
01454 if (A.rowsize()!=A.colsize() || A.rowsize()==0)
01455 HDNUM_ERROR("need square and nonempty matrix");
01456 if (A.rowsize()!=x.size())
01457 HDNUM_ERROR("need A and x of same size");
01458 for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i)
01459 {
01460 REAL p(1.0);
01461 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
01462 {
01463 A[i][j] = p;
01464 p *= x[i];
01465 }
01466 }
01467 }
01468
01470 template<typename REAL>
01471 inline void gnuplot (const std::string& fname, const DenseMatrix<REAL> &A)
01472 {
01473 std::fstream f(fname.c_str(),std::ios::out);
01474 for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i)
01475 {
01476 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
01477 {
01478 if( A.scientific() )
01479 {
01480 f << std::setw(A.width())
01481 << std::scientific
01482 << std::showpoint
01483 << std::setprecision(A.precision()) << A[i][j];
01484 }
01485 else
01486 {
01487 f << std::setw(A.width())
01488 << std::fixed
01489 << std::showpoint
01490 << std::setprecision(A.precision()) << A[i][j];
01491 }
01492 }
01493 f << std::endl;
01494 }
01495 f.close();
01496 }
01497
01498
01499
01529 template<typename REAL>
01530 inline void readMatrixFromFile (const std::string& filename, DenseMatrix<REAL> &A)
01531 {
01532 std::string buffer;
01533 std::ifstream fin( filename.c_str() );
01534 std::size_t i=0;
01535 std::size_t j=0;
01536 if( fin.is_open() ){
01537 while( std::getline( fin, buffer ) ){
01538 std::istringstream iss(buffer);
01539 hdnum::Vector<REAL> rowvector;
01540 while( iss ){
01541 std::string sub;
01542 iss >> sub;
01543
01544 if( sub.length()>0 ){
01545 REAL a = atof(sub.c_str());
01546
01547 rowvector.push_back(a);
01548 }
01549 j++;
01550 }
01551 if( rowvector.size()>0 ){
01552 A.addNewRow( rowvector );
01553 i++;
01554
01555 }
01556 }
01557 fin.close();
01558 }
01559 else{
01560 HDNUM_ERROR("Could not open file!");
01561 }
01562 }
01563
01564 }
01565
01566 #endif // DENSEMATRIX_HH
01567