Heidelberg Educational Numerics Library Version 0.24 (from 9 September 2011)
|
00001 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 00002 /* 00003 * File: densematrix.hh 00004 * Author: ngo 00005 * 00006 * Created on April 15, 2011 00007 */ 00008 00009 #ifndef DENSEMATRIX_HH 00010 #define DENSEMATRIX_HH 00011 00012 #include <iostream> 00013 #include <fstream> 00014 #include <sstream> 00015 #include <string> 00016 #include <iomanip> 00017 #include <cstdlib> 00018 #include "countablearray.hh" 00019 #include "vector.hh" 00020 00021 00022 namespace hdnum { 00023 00027 template<typename REAL> 00028 class DenseMatrix 00029 { 00030 public: 00032 typedef std::size_t size_type; 00033 typedef typename std::vector<REAL> VType; 00034 typedef typename VType::const_iterator ConstVectorIterator; 00035 typedef typename VType::iterator VectorIterator; 00036 00037 private: 00038 VType m_data; // Matrix data is stored in an STL vector! 00039 std::size_t m_rows; // Number of Matrix rows 00040 std::size_t m_cols; // Number of Matrix columns 00041 00042 static bool bScientific; 00043 static std::size_t nIndexWidth; 00044 static std::size_t nValueWidth; 00045 static std::size_t nValuePrecision; 00046 00047 00048 // function to calculate the modulus of a value 00049 REAL myabs (REAL x) const 00050 { 00051 if (x>=REAL(0)) 00052 return x; 00053 else 00054 return -x; 00055 } 00056 00057 00058 // get matrix element for write access: 00059 inline REAL & at(const std::size_t row, const std::size_t col) 00060 { 00061 return m_data[row * m_cols + col]; 00062 } 00063 00064 // get matrix element for read-only access: 00065 inline const REAL & at(const std::size_t row, const std::size_t col) const 00066 { 00067 return m_data[row * m_cols + col]; 00068 } 00069 00070 public: 00071 00072 // default constructor (empty Matrix) 00073 DenseMatrix() 00074 : m_data( 0, 0 ) 00075 , m_rows( 0 ) 00076 , m_cols( 0 ) 00077 { 00078 } 00079 00080 // constructor 00081 DenseMatrix( const std::size_t _rows, 00082 const std::size_t _cols, 00083 const REAL def_val=0 00084 ) 00085 : m_data( _rows*_cols, def_val ) 00086 , m_rows( _rows ) 00087 , m_cols( _cols ) 00088 { 00089 } 00090 00091 void addNewRow( const hdnum::Vector<REAL> & rowvector ){ 00092 m_rows++; 00093 m_cols = rowvector.size(); 00094 for(std::size_t i=0; i<m_cols; i++ ) 00095 m_data.push_back( rowvector[i] ); 00096 } 00097 /* 00098 // copy constructor (not needed, since it inherits from the STL vector) 00099 DenseMatrix( const DenseMatrix& A ) 00100 { 00101 this->m_data = A.m_data; 00102 m_rows = A.m_rows; 00103 m_cols = A.m_cols; 00104 } 00105 */ 00121 size_t rowsize () const 00122 { 00123 return m_rows; 00124 } 00125 00141 size_t colsize () const 00142 { 00143 return m_cols; 00144 } 00145 00146 00147 // pretty-print output properties 00148 bool scientific() const 00149 { 00150 return bScientific; 00151 } 00152 00176 void scientific(bool b) const 00177 { 00178 bScientific=b; 00179 } 00180 00182 std::size_t iwidth () const 00183 { 00184 return nIndexWidth; 00185 } 00186 00188 std::size_t width () const 00189 { 00190 return nValueWidth; 00191 } 00192 00194 std::size_t precision () const 00195 { 00196 return nValuePrecision; 00197 } 00198 00200 void iwidth (std::size_t i) const 00201 { 00202 nIndexWidth=i; 00203 } 00204 00206 void width (std::size_t i) const 00207 { 00208 nValueWidth=i; 00209 } 00210 00212 void precision (std::size_t i) const 00213 { 00214 nValuePrecision=i; 00215 } 00216 00217 00262 // overloaded element access operators 00263 // write access on matrix element A_ij using A(i,j) 00264 inline REAL & operator()(const std::size_t row, const std::size_t col) 00265 { 00266 assert(row < m_rows|| col < m_cols); 00267 return at(row,col); 00268 } 00269 00270 // read-access on matrix element A_ij using A(i,j) 00271 inline const REAL & operator()(const std::size_t row, const std::size_t col) const 00272 { 00273 assert(row < m_rows|| col < m_cols); 00274 return at(row,col); 00275 } 00276 00277 00278 // read-access on matrix element A_ij using A[i][j] 00279 const ConstVectorIterator operator[](const std::size_t row) const 00280 { 00281 assert(row < m_rows); 00282 return m_data.begin() + row * m_cols; 00283 } 00284 00329 // write-access on matrix element A_ij using A[i][j] 00330 VectorIterator operator[](const std::size_t row) 00331 { 00332 assert(row < m_rows); 00333 return m_data.begin() + row * m_cols; 00334 } 00335 00336 00337 00360 DenseMatrix& operator= (const DenseMatrix& A) 00361 { 00362 m_data = A.m_data; 00363 m_rows = A.m_rows; 00364 m_cols = A.m_cols; 00365 return *this; 00366 } 00367 00368 00369 00391 DenseMatrix& operator= (const REAL value) 00392 { 00393 for (std::size_t i=0; i<rowsize(); i++) 00394 for (std::size_t j=0; j<colsize(); j++) 00395 (*this)(i,j) = value; 00396 return *this; 00397 } 00398 00410 DenseMatrix sub (size_type i, size_type j, size_type rows, size_type cols) 00411 { 00412 DenseMatrix A(rows,cols); 00413 DenseMatrix &self = *this; 00414 size_type k1=0, k2=0; 00415 for (size_type i_=i; i_ < i+rows; i_++){ 00416 for (size_type j_=j; j_ < j+cols; j_++){ 00417 A[k1][k2] = self[i_][j_]; 00418 k2++; 00419 } 00420 k1++; 00421 } 00422 return A; 00423 } 00424 00425 00426 00427 // Basic Matrix Operations 00428 00436 DenseMatrix& operator+= (const DenseMatrix& B) 00437 { 00438 for (std::size_t i=0; i<rowsize(); ++i) 00439 for (std::size_t j=0; j<colsize(); ++j) 00440 (*this)(i,j) += B(i,j); 00441 return *this; 00442 } 00443 00451 DenseMatrix& operator-= (const DenseMatrix& B) 00452 { 00453 for (std::size_t i=0; i<rowsize(); ++i) 00454 for (std::size_t j=0; j<colsize(); ++j) 00455 (*this)(i,j) -= B(i,j); 00456 return *this; 00457 } 00458 00459 00489 DenseMatrix& operator*= (const REAL s) 00490 { 00491 for (std::size_t i=0; i<rowsize(); ++i) 00492 for (std::size_t j=0; j<colsize(); ++j) 00493 (*this)(i,j) *= s; 00494 return *this; 00495 } 00496 00497 00528 DenseMatrix& operator/= (const REAL s) 00529 { 00530 for (std::size_t i=0; i<rowsize(); ++i) 00531 for (std::size_t j=0; j<colsize(); ++j) 00532 (*this)(i,j) /= s; 00533 return *this; 00534 } 00535 00536 00563 void update (const REAL s, const DenseMatrix& B) 00564 { 00565 for (std::size_t i=0; i<rowsize(); ++i) 00566 for (std::size_t j=0; j<colsize(); ++j) 00567 (*this)(i,j) += s*B(i,j); 00568 } 00569 00570 00571 00613 template<class V> 00614 void mv (Vector<V>& y, const Vector<V>& x) const 00615 { 00616 if (this->rowsize()!=y.size()) 00617 HDNUM_ERROR("mv: size of A and y do not match"); 00618 if (this->colsize()!=x.size()) 00619 HDNUM_ERROR("mv: size of A and x do not match"); 00620 for (std::size_t i=0; i<rowsize(); ++i) 00621 { 00622 y[i] = 0; 00623 for (std::size_t j=0; j<colsize(); ++j) 00624 y[i] += (*this)(i,j)*x[j]; 00625 } 00626 } 00627 00628 00675 template<class V> 00676 void umv (Vector<V>& y, const Vector<V>& x) const 00677 { 00678 if (this->rowsize()!=y.size()) 00679 HDNUM_ERROR("mv: size of A and y do not match"); 00680 if (this->colsize()!=x.size()) 00681 HDNUM_ERROR("mv: size of A and x do not match"); 00682 for (std::size_t i=0; i<rowsize(); ++i) 00683 { 00684 for (std::size_t j=0; j<colsize(); ++j) 00685 y[i] += (*this)(i,j)*x[j]; 00686 } 00687 } 00688 00689 00738 template<class V> 00739 void umv (Vector<V>& y, const V& s, const Vector<V>& x) const 00740 { 00741 if (this->rowsize()!=y.size()) 00742 HDNUM_ERROR("mv: size of A and y do not match"); 00743 if (this->colsize()!=x.size()) 00744 HDNUM_ERROR("mv: size of A and x do not match"); 00745 for (std::size_t i=0; i<rowsize(); ++i) 00746 { 00747 for (std::size_t j=0; j<colsize(); ++j) 00748 y[i] += s*(*this)(i,j)*x[j]; 00749 } 00750 } 00751 00752 00753 00802 void mm (const DenseMatrix<REAL>& A, const DenseMatrix<REAL>& B) 00803 { 00804 if (this->rowsize()!=A.rowsize()) 00805 HDNUM_ERROR("mm: size incompatible"); 00806 if (this->colsize()!=B.colsize()) 00807 HDNUM_ERROR("mm: size incompatible"); 00808 if (A.colsize()!=B.rowsize()) 00809 HDNUM_ERROR("mm: size incompatible"); 00810 00811 for (std::size_t i=0; i<rowsize(); i++) 00812 for (std::size_t j=0; j<colsize(); j++) 00813 { 00814 (*this)(i,j) = 0; 00815 for (std::size_t k=0; k<A.colsize(); k++) 00816 (*this)(i,j) += A(i,k)*B(k,j); 00817 } 00818 } 00819 00820 00875 void umm (const DenseMatrix<REAL>& A, const DenseMatrix<REAL>& B) 00876 { 00877 if (this->rowsize()!=A.rowsize()) 00878 HDNUM_ERROR("mm: size incompatible"); 00879 if (this->colsize()!=B.colsize()) 00880 HDNUM_ERROR("mm: size incompatible"); 00881 if (A.colsize()!=B.rowsize()) 00882 HDNUM_ERROR("mm: size incompatible"); 00883 00884 for (std::size_t i=0; i<rowsize(); i++) 00885 for (std::size_t j=0; j<colsize(); j++) 00886 for (std::size_t k=0; k<A.colsize(); k++) 00887 (*this)(i,j) += A(i,k)*B(k,j); 00888 } 00889 00890 00891 00926 void sc (const Vector<REAL>& x, std::size_t k) 00927 { 00928 if (this->rowsize()!=x.size()) 00929 HDNUM_ERROR("cc: size incompatible"); 00930 00931 for (std::size_t i=0; i<rowsize(); i++) 00932 (*this)(i,k) = x[i]; 00933 } 00934 00971 void sr (const Vector<REAL>& x, std::size_t k) 00972 { 00973 if (this->colsize()!=x.size()) 00974 HDNUM_ERROR("cc: size incompatible"); 00975 00976 for (std::size_t i=0; i<colsize(); i++) 00977 (*this)(k,i) = x[i]; 00978 } 00979 00980 00982 REAL norm_infty () const 00983 { 00984 REAL norm(0.0); 00985 for (std::size_t i=0; i<rowsize(); i++) 00986 { 00987 REAL sum(0.0); 00988 for (std::size_t j=0; j<colsize(); j++) 00989 sum += myabs((*this)(i,j)); 00990 if (sum>norm) norm = sum; 00991 } 00992 return norm; 00993 } 00994 00996 REAL norm_1 () const 00997 { 00998 REAL norm(0.0); 00999 for (std::size_t j=0; j<colsize(); j++) 01000 { 01001 REAL sum(0.0); 01002 for (std::size_t i=0; i<rowsize(); i++) 01003 sum += myabs((*this)(i,j)); 01004 if (sum>norm) norm = sum; 01005 } 01006 return norm; 01007 } 01008 01009 01010 01057 Vector<REAL> operator* (const Vector<REAL> & x) 01058 { 01059 assert( x.size() == rowsize() ); 01060 01061 Vector<REAL> y( rowsize() ); 01062 for(std::size_t r=0; r<rowsize(); ++r){ 01063 for(std::size_t c=0; c<colsize(); ++c){ 01064 y[r]+= at(r,c) * x[c]; 01065 } 01066 } 01067 return y; 01068 } 01069 01070 01071 01072 01116 DenseMatrix operator* (const DenseMatrix & x) const 01117 { 01118 assert(colsize() == x.rowsize()); 01119 01120 const std::size_t out_rows = rowsize(); 01121 const std::size_t out_cols = x.colsize(); 01122 DenseMatrix y(out_rows, out_cols,0.0); 01123 for(std::size_t r=0; r<out_rows; ++r) 01124 for(std::size_t c=0; c<out_cols; ++c) 01125 for(std::size_t i=0; i<colsize(); ++i) 01126 y(r,c) += at(r,i) * x(i,c); 01127 01128 return y; 01129 } 01130 01131 01132 01176 DenseMatrix operator+ (const DenseMatrix & x) const 01177 { 01178 assert(colsize() == x.rowsize()); 01179 01180 const std::size_t out_rows = rowsize(); 01181 const std::size_t out_cols = x.colsize(); 01182 DenseMatrix y(out_rows, out_cols,0.0); 01183 y = *this; 01184 y+=x; 01185 return y; 01186 } 01187 01188 01189 01233 DenseMatrix operator- (const DenseMatrix & x) const 01234 { 01235 assert(colsize() == x.rowsize()); 01236 01237 const std::size_t out_rows = rowsize(); 01238 const std::size_t out_cols = x.colsize(); 01239 DenseMatrix y(out_rows, out_cols,0.0); 01240 y = *this; 01241 y-=x; 01242 return y; 01243 } 01244 01245 01246 }; 01247 01248 01249 01250 template<typename REAL> 01251 bool DenseMatrix<REAL>::bScientific = true; 01252 template<typename REAL> 01253 std::size_t DenseMatrix<REAL>::nIndexWidth = 10; 01254 template<typename REAL> 01255 std::size_t DenseMatrix<REAL>::nValueWidth = 10; 01256 template<typename REAL> 01257 std::size_t DenseMatrix<REAL>::nValuePrecision = 3; 01258 01259 01283 template <typename REAL> 01284 inline std::ostream& operator<< (std::ostream& s, const DenseMatrix<REAL>& A) 01285 { 01286 s << std::endl; 01287 s << " " << std::setw(A.iwidth()) << " " << " "; 01288 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j) 01289 s << std::setw(A.width()) << j << " "; 01290 s << std::endl; 01291 01292 for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i) 01293 { 01294 s << " " << std::setw(A.iwidth()) << i << " "; 01295 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j) 01296 { 01297 if( A.scientific() ) 01298 { 01299 s << std::setw(A.width()) 01300 << std::scientific 01301 << std::showpoint 01302 << std::setprecision(A.precision()) 01303 << A[i][j] << " "; 01304 } 01305 else 01306 { 01307 s << std::setw(A.width()) 01308 << std::fixed 01309 << std::showpoint 01310 << std::setprecision(A.precision()) 01311 << A[i][j] << " "; 01312 } 01313 } 01314 s << std::endl; 01315 } 01316 return s; 01317 } 01318 01325 template<typename REAL> 01326 inline void fill (DenseMatrix<REAL> A, const REAL& t) 01327 { 01328 for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i) 01329 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j) 01330 A[i][j] = t; 01331 } 01332 01334 template<typename REAL> 01335 inline void zero (DenseMatrix<REAL> &A) 01336 { 01337 for (std::size_t i=0; i<A.rowsize(); ++i) 01338 for (std::size_t j=0; j<A.colsize(); ++j) 01339 A(i,j) = REAL(0); 01340 } 01341 01375 template<class T> 01376 inline void identity (DenseMatrix<T> &A) 01377 { 01378 for (typename DenseMatrix<T>::size_type i=0; i<A.rowsize(); ++i) 01379 for (typename DenseMatrix<T>::size_type j=0; j<A.colsize(); ++j) 01380 if (i==j) 01381 A[i][i] = T(1); 01382 else 01383 A[i][j] = T(0); 01384 } 01385 01421 template<typename REAL> 01422 inline void spd (DenseMatrix<REAL> &A) 01423 { 01424 if (A.rowsize()!=A.colsize() || A.rowsize()==0) 01425 HDNUM_ERROR("need square and nonempty matrix"); 01426 for (std::size_t i=0; i<A.rowsize(); ++i) 01427 for (std::size_t j=0; j<A.colsize(); ++j) 01428 if (i==j) 01429 A(i,i) = REAL(4.0); 01430 else 01431 A(i,j) = - REAL(1.0)/((i-j)*(i-j)); 01432 } 01433 01483 template<typename REAL> 01484 inline void vandermonde (DenseMatrix<REAL> &A, const Vector<REAL> x) 01485 { 01486 if (A.rowsize()!=A.colsize() || A.rowsize()==0) 01487 HDNUM_ERROR("need square and nonempty matrix"); 01488 if (A.rowsize()!=x.size()) 01489 HDNUM_ERROR("need A and x of same size"); 01490 for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i) 01491 { 01492 REAL p(1.0); 01493 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j) 01494 { 01495 A[i][j] = p; 01496 p *= x[i]; 01497 } 01498 } 01499 } 01500 01502 template<typename REAL> 01503 inline void gnuplot (const std::string& fname, const DenseMatrix<REAL> &A) 01504 { 01505 std::fstream f(fname.c_str(),std::ios::out); 01506 for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i) 01507 { 01508 for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j) 01509 { 01510 if( A.scientific() ) 01511 { 01512 f << std::setw(A.width()) 01513 << std::scientific 01514 << std::showpoint 01515 << std::setprecision(A.precision()) << A[i][j]; 01516 } 01517 else 01518 { 01519 f << std::setw(A.width()) 01520 << std::fixed 01521 << std::showpoint 01522 << std::setprecision(A.precision()) << A[i][j]; 01523 } 01524 } 01525 f << std::endl; 01526 } 01527 f.close(); 01528 } 01529 01530 01531 01561 template<typename REAL> 01562 inline void readMatrixFromFile (const std::string& filename, DenseMatrix<REAL> &A) 01563 { 01564 std::string buffer; 01565 std::ifstream fin( filename.c_str() ); 01566 std::size_t i=0; 01567 std::size_t j=0; 01568 if( fin.is_open() ){ 01569 while( std::getline( fin, buffer ) ){ 01570 std::istringstream iss(buffer); 01571 hdnum::Vector<REAL> rowvector; 01572 while( iss ){ 01573 std::string sub; 01574 iss >> sub; 01575 //std::cout << " sub = " << sub.c_str() << ": "; 01576 if( sub.length()>0 ){ 01577 REAL a = atof(sub.c_str()); 01578 //std::cout << std::fixed << std::setw(10) << std::setprecision(5) << a; 01579 rowvector.push_back(a); 01580 } 01581 j++; 01582 } 01583 if( rowvector.size()>0 ){ 01584 A.addNewRow( rowvector ); 01585 i++; 01586 //std::cout << std::endl; 01587 } 01588 } 01589 fin.close(); 01590 } 01591 else{ 01592 HDNUM_ERROR("Could not open file!"); 01593 } 01594 } 01595 01596 } 01597 01598 #endif // DENSEMATRIX_HH 01599