Heidelberg Educational Numerics Library Version 0.24 (from 9 September 2011)

src/densematrix.hh

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