Heidelberg Educational Numerics Library  Version 0.24 (from 9 September 2011)
densematrix.hh
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 /*
3  * File: densematrix.hh
4  * Author: ngo
5  *
6  * Created on April 15, 2011
7  */
8 
9 #ifndef DENSEMATRIX_HH
10 #define DENSEMATRIX_HH
11 
12 #include <iostream>
13 #include <fstream>
14 #include <sstream>
15 #include <string>
16 #include <iomanip>
17 #include <cstdlib>
18 #include "vector.hh"
19 
20 
21 namespace hdnum {
22 
25  template<typename REAL>
27  {
28  public:
30  typedef std::size_t size_type;
31  typedef typename std::vector<REAL> VType;
32  typedef typename VType::const_iterator ConstVectorIterator;
33  typedef typename VType::iterator VectorIterator;
34 
35  private:
36  VType m_data; // Matrix data is stored in an STL vector!
37  std::size_t m_rows; // Number of Matrix rows
38  std::size_t m_cols; // Number of Matrix columns
39 
40  static bool bScientific;
41  static std::size_t nIndexWidth;
42  static std::size_t nValueWidth;
43  static std::size_t nValuePrecision;
44 
45 
47  REAL myabs (REAL x) const
48  {
49  if (x>=REAL(0))
50  return x;
51  else
52  return -x;
53  }
54 
55 
57  inline REAL & at(const std::size_t row, const std::size_t col)
58  {
59  return m_data[row * m_cols + col];
60  }
61 
63  inline const REAL & at(const std::size_t row, const std::size_t col) const
64  {
65  return m_data[row * m_cols + col];
66  }
67 
68  public:
69 
72  : m_data( 0, 0 )
73  , m_rows( 0 )
74  , m_cols( 0 )
75  {
76  }
77 
79  DenseMatrix( const std::size_t _rows,
80  const std::size_t _cols,
81  const REAL def_val=0
82  )
83  : m_data( _rows*_cols, def_val )
84  , m_rows( _rows )
85  , m_cols( _cols )
86  {
87  }
88 
89  void addNewRow( const hdnum::Vector<REAL> & rowvector ){
90  m_rows++;
91  m_cols = rowvector.size();
92  for(std::size_t i=0; i<m_cols; i++ )
93  m_data.push_back( rowvector[i] );
94  }
95 
96  /*
97  // copy constructor (not needed, since it inherits from the STL vector)
98  DenseMatrix( const DenseMatrix& A )
99  {
100  this->m_data = A.m_data;
101  m_rows = A.m_rows;
102  m_cols = A.m_cols;
103  }
104  */
105 
121  size_t rowsize () const
122  {
123  return m_rows;
124  }
125 
141  size_t colsize () const
142  {
143  return m_cols;
144  }
145 
146 
147  // pretty-print output properties
148  bool scientific() const
149  {
150  return bScientific;
151  }
152 
176  void scientific(bool b) const
177  {
178  bScientific=b;
179  }
180 
182  std::size_t iwidth () const
183  {
184  return nIndexWidth;
185  }
186 
188  std::size_t width () const
189  {
190  return nValueWidth;
191  }
192 
194  std::size_t precision () const
195  {
196  return nValuePrecision;
197  }
198 
200  void iwidth (std::size_t i) const
201  {
202  nIndexWidth=i;
203  }
204 
206  void width (std::size_t i) const
207  {
208  nValueWidth=i;
209  }
210 
212  void precision (std::size_t i) const
213  {
214  nValuePrecision=i;
215  }
216 
217 
262  // overloaded element access operators
263  // write access on matrix element A_ij using A(i,j)
264  inline REAL & operator()(const std::size_t row, const std::size_t col)
265  {
266  assert(row < m_rows|| col < m_cols);
267  return at(row,col);
268  }
269 
271  inline const REAL & operator()(const std::size_t row, const std::size_t col) const
272  {
273  assert(row < m_rows|| col < m_cols);
274  return at(row,col);
275  }
276 
277 
279  const ConstVectorIterator operator[](const std::size_t row) const
280  {
281  assert(row < m_rows);
282  return m_data.begin() + row * m_cols;
283  }
284 
286  VectorIterator operator[](const std::size_t row)
287  {
288  assert(row < m_rows);
289  return m_data.begin() + row * m_cols;
290  }
291 
292 
293 
317  {
318  m_data = A.m_data;
319  m_rows = A.m_rows;
320  m_cols = A.m_cols;
321  return *this;
322  }
323 
324 
325 
347  DenseMatrix& operator= (const REAL value)
348  {
349  for (std::size_t i=0; i<rowsize(); i++)
350  for (std::size_t j=0; j<colsize(); j++)
351  (*this)(i,j) = value;
352  return *this;
353  }
354 
366  DenseMatrix sub (size_type i, size_type j, size_type rows, size_type cols)
367  {
368  DenseMatrix A(rows,cols);
369  DenseMatrix &self = *this;
370  size_type k1=0, k2=0;
371  for (size_type i_=i; i_ < i+rows; i_++){
372  for (size_type j_=j; j_ < j+cols; j_++){
373  A[k1][k2] = self[i_][j_];
374  k2++;
375  }
376  k1++;
377  }
378  return A;
379  }
380 
381 
382 
383  // Basic Matrix Operations
384 
393  {
394  for (std::size_t i=0; i<rowsize(); ++i)
395  for (std::size_t j=0; j<colsize(); ++j)
396  (*this)(i,j) += B(i,j);
397  return *this;
398  }
399 
408  {
409  for (std::size_t i=0; i<rowsize(); ++i)
410  for (std::size_t j=0; j<colsize(); ++j)
411  (*this)(i,j) -= B(i,j);
412  return *this;
413  }
414 
415 
445  DenseMatrix& operator*= (const REAL s)
446  {
447  for (std::size_t i=0; i<rowsize(); ++i)
448  for (std::size_t j=0; j<colsize(); ++j)
449  (*this)(i,j) *= s;
450  return *this;
451  }
452 
453 
484  DenseMatrix& operator/= (const REAL s)
485  {
486  for (std::size_t i=0; i<rowsize(); ++i)
487  for (std::size_t j=0; j<colsize(); ++j)
488  (*this)(i,j) /= s;
489  return *this;
490  }
491 
492 
519  void update (const REAL s, const DenseMatrix& B)
520  {
521  for (std::size_t i=0; i<rowsize(); ++i)
522  for (std::size_t j=0; j<colsize(); ++j)
523  (*this)(i,j) += s*B(i,j);
524  }
525 
526 
527 
569  template<class V>
570  void mv (Vector<V>& y, const Vector<V>& x) const
571  {
572  if (this->rowsize()!=y.size())
573  HDNUM_ERROR("mv: size of A and y do not match");
574  if (this->colsize()!=x.size())
575  HDNUM_ERROR("mv: size of A and x do not match");
576  for (std::size_t i=0; i<rowsize(); ++i)
577  {
578  y[i] = 0;
579  for (std::size_t j=0; j<colsize(); ++j)
580  y[i] += (*this)(i,j)*x[j];
581  }
582  }
583 
584 
631  template<class V>
632  void umv (Vector<V>& y, const Vector<V>& x) const
633  {
634  if (this->rowsize()!=y.size())
635  HDNUM_ERROR("mv: size of A and y do not match");
636  if (this->colsize()!=x.size())
637  HDNUM_ERROR("mv: size of A and x do not match");
638  for (std::size_t i=0; i<rowsize(); ++i)
639  {
640  for (std::size_t j=0; j<colsize(); ++j)
641  y[i] += (*this)(i,j)*x[j];
642  }
643  }
644 
645 
694  template<class V>
695  void umv (Vector<V>& y, const V& s, const Vector<V>& x) const
696  {
697  if (this->rowsize()!=y.size())
698  HDNUM_ERROR("mv: size of A and y do not match");
699  if (this->colsize()!=x.size())
700  HDNUM_ERROR("mv: size of A and x do not match");
701  for (std::size_t i=0; i<rowsize(); ++i)
702  {
703  for (std::size_t j=0; j<colsize(); ++j)
704  y[i] += s*(*this)(i,j)*x[j];
705  }
706  }
707 
708 
709 
758  void mm (const DenseMatrix<REAL>& A, const DenseMatrix<REAL>& B)
759  {
760  if (this->rowsize()!=A.rowsize())
761  HDNUM_ERROR("mm: size incompatible");
762  if (this->colsize()!=B.colsize())
763  HDNUM_ERROR("mm: size incompatible");
764  if (A.colsize()!=B.rowsize())
765  HDNUM_ERROR("mm: size incompatible");
766 
767  for (std::size_t i=0; i<rowsize(); i++)
768  for (std::size_t j=0; j<colsize(); j++)
769  {
770  (*this)(i,j) = 0;
771  for (std::size_t k=0; k<A.colsize(); k++)
772  (*this)(i,j) += A(i,k)*B(k,j);
773  }
774  }
775 
776 
831  void umm (const DenseMatrix<REAL>& A, const DenseMatrix<REAL>& B)
832  {
833  if (this->rowsize()!=A.rowsize())
834  HDNUM_ERROR("mm: size incompatible");
835  if (this->colsize()!=B.colsize())
836  HDNUM_ERROR("mm: size incompatible");
837  if (A.colsize()!=B.rowsize())
838  HDNUM_ERROR("mm: size incompatible");
839 
840  for (std::size_t i=0; i<rowsize(); i++)
841  for (std::size_t j=0; j<colsize(); j++)
842  for (std::size_t k=0; k<A.colsize(); k++)
843  (*this)(i,j) += A(i,k)*B(k,j);
844  }
845 
846 
847 
882  void sc (const Vector<REAL>& x, std::size_t k)
883  {
884  if (this->rowsize()!=x.size())
885  HDNUM_ERROR("cc: size incompatible");
886 
887  for (std::size_t i=0; i<rowsize(); i++)
888  (*this)(i,k) = x[i];
889  }
890 
927  void sr (const Vector<REAL>& x, std::size_t k)
928  {
929  if (this->colsize()!=x.size())
930  HDNUM_ERROR("cc: size incompatible");
931 
932  for (std::size_t i=0; i<colsize(); i++)
933  (*this)(k,i) = x[i];
934  }
935 
936 
938  REAL norm_infty () const
939  {
940  REAL norm(0.0);
941  for (std::size_t i=0; i<rowsize(); i++)
942  {
943  REAL sum(0.0);
944  for (std::size_t j=0; j<colsize(); j++)
945  sum += myabs((*this)(i,j));
946  if (sum>norm) norm = sum;
947  }
948  return norm;
949  }
950 
952  REAL norm_1 () const
953  {
954  REAL norm(0.0);
955  for (std::size_t j=0; j<colsize(); j++)
956  {
957  REAL sum(0.0);
958  for (std::size_t i=0; i<rowsize(); i++)
959  sum += myabs((*this)(i,j));
960  if (sum>norm) norm = sum;
961  }
962  return norm;
963  }
964 
965 
966 
1014  {
1015  assert( x.size() == rowsize() );
1016 
1017  Vector<REAL> y( rowsize() );
1018  for(std::size_t r=0; r<rowsize(); ++r){
1019  for(std::size_t c=0; c<colsize(); ++c){
1020  y[r]+= at(r,c) * x[c];
1021  }
1022  }
1023  return y;
1024  }
1025 
1026 
1027 
1028 
1073  {
1074  assert(colsize() == x.rowsize());
1075 
1076  const std::size_t out_rows = rowsize();
1077  const std::size_t out_cols = x.colsize();
1078  DenseMatrix y(out_rows, out_cols,0.0);
1079  for(std::size_t r=0; r<out_rows; ++r)
1080  for(std::size_t c=0; c<out_cols; ++c)
1081  for(std::size_t i=0; i<colsize(); ++i)
1082  y(r,c) += at(r,i) * x(i,c);
1083 
1084  return y;
1085  }
1086 
1087 
1088 
1133  {
1134  assert(colsize() == x.rowsize());
1135 
1136  const std::size_t out_rows = rowsize();
1137  const std::size_t out_cols = x.colsize();
1138  DenseMatrix y(out_rows, out_cols,0.0);
1139  y = *this;
1140  y+=x;
1141  return y;
1142  }
1143 
1144 
1145 
1190  {
1191  assert(colsize() == x.rowsize());
1192 
1193  const std::size_t out_rows = rowsize();
1194  const std::size_t out_cols = x.colsize();
1195  DenseMatrix y(out_rows, out_cols,0.0);
1196  y = *this;
1197  y-=x;
1198  return y;
1199  }
1200 
1201 
1202  };
1203 
1204 
1205 
1206  template<typename REAL>
1207  bool DenseMatrix<REAL>::bScientific = true;
1208  template<typename REAL>
1209  std::size_t DenseMatrix<REAL>::nIndexWidth = 10;
1210  template<typename REAL>
1211  std::size_t DenseMatrix<REAL>::nValueWidth = 10;
1212  template<typename REAL>
1213  std::size_t DenseMatrix<REAL>::nValuePrecision = 3;
1214 
1215 
1239  template <typename REAL>
1240  inline std::ostream& operator<< (std::ostream& s, const DenseMatrix<REAL>& A)
1241  {
1242  s << std::endl;
1243  s << " " << std::setw(A.iwidth()) << " " << " ";
1244  for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
1245  s << std::setw(A.width()) << j << " ";
1246  s << std::endl;
1247 
1248  for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i)
1249  {
1250  s << " " << std::setw(A.iwidth()) << i << " ";
1251  for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
1252  {
1253  if( A.scientific() )
1254  {
1255  s << std::setw(A.width())
1256  << std::scientific
1257  << std::showpoint
1258  << std::setprecision(A.precision())
1259  << A[i][j] << " ";
1260  }
1261  else
1262  {
1263  s << std::setw(A.width())
1264  << std::fixed
1265  << std::showpoint
1266  << std::setprecision(A.precision())
1267  << A[i][j] << " ";
1268  }
1269  }
1270  s << std::endl;
1271  }
1272  return s;
1273  }
1274 
1281  template<typename REAL>
1282  inline void fill (DenseMatrix<REAL> A, const REAL& t)
1283  {
1284  for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i)
1285  for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
1286  A[i][j] = t;
1287  }
1288 
1290  template<typename REAL>
1291  inline void zero (DenseMatrix<REAL> &A)
1292  {
1293  for (std::size_t i=0; i<A.rowsize(); ++i)
1294  for (std::size_t j=0; j<A.colsize(); ++j)
1295  A(i,j) = REAL(0);
1296  }
1297 
1331  template<class T>
1332  inline void identity (DenseMatrix<T> &A)
1333  {
1334  for (typename DenseMatrix<T>::size_type i=0; i<A.rowsize(); ++i)
1335  for (typename DenseMatrix<T>::size_type j=0; j<A.colsize(); ++j)
1336  if (i==j)
1337  A[i][i] = T(1);
1338  else
1339  A[i][j] = T(0);
1340  }
1341 
1377  template<typename REAL>
1378  inline void spd (DenseMatrix<REAL> &A)
1379  {
1380  if (A.rowsize()!=A.colsize() || A.rowsize()==0)
1381  HDNUM_ERROR("need square and nonempty matrix");
1382  for (std::size_t i=0; i<A.rowsize(); ++i)
1383  for (std::size_t j=0; j<A.colsize(); ++j)
1384  if (i==j)
1385  A(i,i) = REAL(4.0);
1386  else
1387  A(i,j) = - REAL(1.0)/((i-j)*(i-j));
1388  }
1389 
1439  template<typename REAL>
1440  inline void vandermonde (DenseMatrix<REAL> &A, const Vector<REAL> x)
1441  {
1442  if (A.rowsize()!=A.colsize() || A.rowsize()==0)
1443  HDNUM_ERROR("need square and nonempty matrix");
1444  if (A.rowsize()!=x.size())
1445  HDNUM_ERROR("need A and x of same size");
1446  for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i)
1447  {
1448  REAL p(1.0);
1449  for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
1450  {
1451  A[i][j] = p;
1452  p *= x[i];
1453  }
1454  }
1455  }
1456 
1458  template<typename REAL>
1459  inline void gnuplot (const std::string& fname, const DenseMatrix<REAL> &A)
1460  {
1461  std::fstream f(fname.c_str(),std::ios::out);
1462  for (typename DenseMatrix<REAL>::size_type i=0; i<A.rowsize(); ++i)
1463  {
1464  for (typename DenseMatrix<REAL>::size_type j=0; j<A.colsize(); ++j)
1465  {
1466  if( A.scientific() )
1467  {
1468  f << std::setw(A.width())
1469  << std::scientific
1470  << std::showpoint
1471  << std::setprecision(A.precision()) << A[i][j];
1472  }
1473  else
1474  {
1475  f << std::setw(A.width())
1476  << std::fixed
1477  << std::showpoint
1478  << std::setprecision(A.precision()) << A[i][j];
1479  }
1480  }
1481  f << std::endl;
1482  }
1483  f.close();
1484  }
1485 
1486 
1487 
1517  template<typename REAL>
1518  inline void readMatrixFromFile (const std::string& filename, DenseMatrix<REAL> &A)
1519  {
1520  std::string buffer;
1521  std::ifstream fin( filename.c_str() );
1522  std::size_t i=0;
1523  std::size_t j=0;
1524  if( fin.is_open() ){
1525  while( std::getline( fin, buffer ) ){
1526  std::istringstream iss(buffer);
1527  hdnum::Vector<REAL> rowvector;
1528  while( iss ){
1529  std::string sub;
1530  iss >> sub;
1531  //std::cout << " sub = " << sub.c_str() << ": ";
1532  if( sub.length()>0 ){
1533  REAL a = atof(sub.c_str());
1534  //std::cout << std::fixed << std::setw(10) << std::setprecision(5) << a;
1535  rowvector.push_back(a);
1536  }
1537  j++;
1538  }
1539  if( rowvector.size()>0 ){
1540  A.addNewRow( rowvector );
1541  i++;
1542  //std::cout << std::endl;
1543  }
1544  }
1545  fin.close();
1546  }
1547  else{
1548  HDNUM_ERROR("Could not open file!");
1549  }
1550  }
1551 
1552 }
1553 
1554 #endif // DENSEMATRIX_HH
1555 
Class with mathematical vector operations.
Definition: vector.hh:28
DenseMatrix operator-(const DenseMatrix &x) const
matrix = matrix - matrix
Definition: densematrix.hh:1189
void iwidth(std::size_t i) const
set index field width for pretty-printing
Definition: densematrix.hh:200
REAL & operator()(const std::size_t row, const std::size_t col)
(i,j)-operator for accessing entries of a (m x n)-matrix directly
Definition: densematrix.hh:264
VectorIterator operator[](const std::size_t row)
write-access on matrix element A_ij using A[i][j]
Definition: densematrix.hh:286
DenseMatrix & operator-=(const DenseMatrix &B)
Subtraction assignment.
Definition: densematrix.hh:407
void vandermonde(DenseMatrix< REAL > &A, const Vector< REAL > x)
Definition: densematrix.hh:1440
void mm(const DenseMatrix< REAL > &A, const DenseMatrix< REAL > &B)
assign to matrix product C = A*B to matrix C
Definition: densematrix.hh:758
REAL norm_infty() const
compute row sum norm
Definition: densematrix.hh:938
DenseMatrix & operator=(const DenseMatrix &A)
assignment operator
Definition: densematrix.hh:316
void umm(const DenseMatrix< REAL > &A, const DenseMatrix< REAL > &B)
add matrix product A*B to matrix C
Definition: densematrix.hh:831
void umv(Vector< V > &y, const Vector< V > &x) const
update matrix vector product y += A*x
Definition: densematrix.hh:632
void sr(const Vector< REAL > &x, std::size_t k)
set row: make x the k&#39;th row of A
Definition: densematrix.hh:927
DenseMatrix & operator+=(const DenseMatrix &B)
Addition assignment.
Definition: densematrix.hh:392
DenseMatrix(const std::size_t _rows, const std::size_t _cols, const REAL def_val=0)
constructor
Definition: densematrix.hh:79
DenseMatrix & operator*=(const REAL s)
Scalar multiplication assignment.
Definition: densematrix.hh:445
void width(std::size_t i) const
set data field width for pretty-printing
Definition: densematrix.hh:206
std::size_t width() const
get data field width for pretty-printing
Definition: densematrix.hh:188
DenseMatrix operator+(const DenseMatrix &x) const
matrix = matrix + matrix
Definition: densematrix.hh:1132
size_t rowsize() const
get number of rows of the matrix
Definition: densematrix.hh:121
DenseMatrix()
default constructor (empty Matrix)
Definition: densematrix.hh:71
size_t colsize() const
get number of columns of the matrix
Definition: densematrix.hh:141
std::size_t size_type
Type used for array indices.
Definition: densematrix.hh:30
void sc(const Vector< REAL > &x, std::size_t k)
set column: make x the k&#39;th column of A
Definition: densematrix.hh:882
DenseMatrix sub(size_type i, size_type j, size_type rows, size_type cols)
Submatrix extraction.
Definition: densematrix.hh:366
void spd(DenseMatrix< REAL > &A)
Definition: densematrix.hh:1378
void precision(std::size_t i) const
set data precision for pretty-printing
Definition: densematrix.hh:212
void readMatrixFromFile(const std::string &filename, DenseMatrix< REAL > &A)
Read matrix from a text file.
Definition: densematrix.hh:1518
const REAL & operator()(const std::size_t row, const std::size_t col) const
read-access on matrix element A_ij using A(i,j)
Definition: densematrix.hh:271
void update(const REAL s, const DenseMatrix &B)
Scaled update of a Matrix.
Definition: densematrix.hh:519
const ConstVectorIterator operator[](const std::size_t row) const
read-access on matrix element A_ij using A[i][j]
Definition: densematrix.hh:279
void identity(DenseMatrix< T > &A)
Definition: densematrix.hh:1332
DenseMatrix & operator/=(const REAL s)
Scalar division assignment.
Definition: densematrix.hh:484
Class with mathematical matrix operations.
Definition: densematrix.hh:26
std::size_t iwidth() const
get index field width for pretty-printing
Definition: densematrix.hh:182
void mv(Vector< V > &y, const Vector< V > &x) const
matrix vector product y = A*x
Definition: densematrix.hh:570
std::size_t precision() const
get data precision for pretty-printing
Definition: densematrix.hh:194
void umv(Vector< V > &y, const V &s, const Vector< V > &x) const
update matrix vector product y += sA*x
Definition: densematrix.hh:695
Definition: densematrix.hh:21
Vector< REAL > operator*(const Vector< REAL > &x)
vector = matrix * vector
Definition: densematrix.hh:1013
void scientific(bool b) const
Switch between floating point (default=true) and fixed point (false) display.
Definition: densematrix.hh:176
REAL norm_1() const
compute column sum norm
Definition: densematrix.hh:952