00001
00002 #ifndef HDNUM_MATRIX_HH
00003 #define HDNUM_MATRIX_HH
00004
00005 #include <iostream>
00006 #include <iomanip>
00007 #include <string>
00008 #include <fstream>
00009
00010 #include "countablearray.hh"
00011 #include "exceptions.hh"
00012 #include "vector.hh"
00013
00018 namespace hdnum {
00019
00027 template<class T>
00028 class Matrix {
00029
00030 typedef CountableArray<T> ArrayType;
00031
00032 public:
00033
00035 typedef T value_type;
00036
00038 typedef value_type& reference;
00039
00041 typedef const value_type& const_reference;
00042
00044 typedef std::size_t size_type;
00045
00047 typedef std::ptrdiff_t difference_type;
00048
00050 Matrix () : base(), m(0), n(0), stride(0), data(0)
00051 {}
00052
00054 Matrix (size_type _m, size_type _n)
00055 : base(new ArrayType(_m*_n)), m(_m), n(_n), stride(_n)
00056 {
00057 data = &((*base)[0]);
00058 }
00059
00061 Matrix (size_type _m, size_type _n, const T& _t)
00062 : base(new ArrayType(_m*_n,_t)), m(_m), n(_n), stride(_n)
00063 {
00064 data = &((*base)[0]);
00065 }
00066
00068 Matrix (const Matrix& A)
00069 : base(A.base), m(A.m), n(A.n), stride(A.stride), data(A.data)
00070 {}
00071
00073 Matrix& operator= (const Matrix& A)
00074 {
00075 base = A.base;
00076 m = A.m;
00077 n = A.n;
00078 stride = A.stride;
00079 data = A.data;
00080 return *this;
00081 }
00082
00084 Matrix& operator= (const T& t)
00085 {
00086 for (size_type i=0; i<rowsize(); i++)
00087 for (size_type j=0; j<colsize(); j++)
00088 (*this)[i][j] = t;
00089 return *this;
00090 }
00091
00093 Matrix<T> sub (size_type i, size_type j, size_type rows, size_type cols)
00094 {
00095 Matrix<T> A;
00096 A.base = base;
00097 A.stride = stride;
00098 A.m = rows;
00099 A.n = cols;
00100 A.data = data+i*stride+j;
00101 return A;
00102 }
00103
00105 T* operator[] (size_type i)
00106 {
00107 return data+i*stride;
00108 }
00109
00111 const T* operator[] (size_type i) const
00112 {
00113 return data+i*stride;
00114 }
00115
00123 Matrix& operator+= (const Matrix& B)
00124 {
00125 for (size_type i=0; i<m; ++i)
00126 for (size_type j=0; j<n; ++j)
00127 (*this)[i][j] += B[i][j];
00128 return *this;
00129 }
00130
00138 Matrix& operator-= (const Matrix& B)
00139 {
00140 for (size_type i=0; i<m; ++i)
00141 for (size_type j=0; j<n; ++j)
00142 (*this)[i][j] -= B[i][j];
00143 return *this;
00144 }
00145
00153
00154 Matrix& operator*= (const T& s)
00155 {
00156 for (size_type i=0; i<m; ++i)
00157 for (size_type j=0; j<n; ++j)
00158 (*this)[i][j] *= s;
00159 return *this;
00160 }
00161
00169
00170 Matrix& operator/= (const T& s)
00171 {
00172 for (size_type i=0; i<m; ++i)
00173 for (size_type j=0; j<n; ++j)
00174 (*this)[i][j] /= s;
00175 return *this;
00176 }
00177
00186 void update (const T& s, const Matrix& B)
00187 {
00188 for (size_type i=0; i<m; ++i)
00189 for (size_type j=0; j<n; ++j)
00190 (*this)[i][j] += s*B[i][j];
00191 }
00192
00193
00195 template<class V>
00196 void mv (Vector<V>& y, const Vector<V>& x) const
00197 {
00198 if (this->rowsize()!=y.size())
00199 HDNUM_ERROR("mv: size of A and y do not match");
00200 if (this->colsize()!=x.size())
00201 HDNUM_ERROR("mv: size of A and x do not match");
00202 for (size_type i=0; i<rowsize(); i++)
00203 {
00204 y[i] = 0;
00205 for (size_type j=0; j<colsize(); j++)
00206 y[i] += (*this)[i][j]*x[j];
00207 }
00208 }
00209
00211 template<class V>
00212 void umv (Vector<V>& y, const Vector<V>& x) const
00213 {
00214 if (this->rowsize()!=y.size())
00215 HDNUM_ERROR("mv: size of A and y do not match");
00216 if (this->colsize()!=x.size())
00217 HDNUM_ERROR("mv: size of A and x do not match");
00218 for (size_type i=0; i<rowsize(); i++)
00219 {
00220 for (size_type j=0; j<colsize(); j++)
00221 y[i] += (*this)[i][j]*x[j];
00222 }
00223 }
00224
00226 template<class V>
00227 void umv (Vector<V>& y, const V& s, const Vector<V>& x) const
00228 {
00229 if (this->rowsize()!=y.size())
00230 HDNUM_ERROR("mv: size of A and y do not match");
00231 if (this->colsize()!=x.size())
00232 HDNUM_ERROR("mv: size of A and x do not match");
00233 for (size_type i=0; i<rowsize(); i++)
00234 {
00235 for (size_type j=0; j<colsize(); j++)
00236 y[i] += s*(*this)[i][j]*x[j];
00237 }
00238 }
00239
00241 void mm (const Matrix<T>& A, const Matrix<T>& B)
00242 {
00243 if (this->rowsize()!=A.rowsize())
00244 HDNUM_ERROR("mm: size incompatible");
00245 if (this->colsize()!=B.colsize())
00246 HDNUM_ERROR("mm: size incompatible");
00247 if (A.colsize()!=B.rowsize())
00248 HDNUM_ERROR("mm: size incompatible");
00249
00250 for (size_type i=0; i<rowsize(); i++)
00251 for (size_type j=0; j<colsize(); j++)
00252 {
00253 (*this)[i][j] = 0;
00254 for (size_type k=0; k<A.colsize(); k++)
00255 (*this)[i][j] += A[i][k]*B[k][j];
00256 }
00257 }
00258
00260 void umm (const Matrix<T>& A, const Matrix<T>& B)
00261 {
00262 if (this->rowsize()!=A.rowsize())
00263 HDNUM_ERROR("mm: size incompatible");
00264 if (this->colsize()!=B.colsize())
00265 HDNUM_ERROR("mm: size incompatible");
00266 if (A.colsize()!=B.rowsize())
00267 HDNUM_ERROR("mm: size incompatible");
00268
00269 for (size_type i=0; i<rowsize(); i++)
00270 for (size_type j=0; j<colsize(); j++)
00271 for (size_type k=0; k<A.colsize(); k++)
00272 (*this)[i][j] += A[i][k]*B[k][j];
00273 }
00274
00276 void sc (const Vector<T>& x, size_type k)
00277 {
00278 if (this->rowsize()!=x.size())
00279 HDNUM_ERROR("cc: size incompatible");
00280
00281 for (size_type i=0; i<rowsize(); i++)
00282 (*this)[i][k] = x[i];
00283 }
00284
00286 void sr (const Vector<T>& x, size_type k)
00287 {
00288 if (this->colsize()!=x.size())
00289 HDNUM_ERROR("cc: size incompatible");
00290
00291 for (size_type i=0; i<colsize(); i++)
00292 (*this)[k][i] = x[i];
00293 }
00294
00296 T norm_infty () const
00297 {
00298 T norm(0.0);
00299 for (size_type i=0; i<rowsize(); i++)
00300 {
00301 T sum(0.0);
00302 for (size_type j=0; j<colsize(); j++)
00303 sum += myabs((*this)[i][j]);
00304 if (sum>norm) norm = sum;
00305 }
00306 return norm;
00307 }
00308
00310 T norm_1 () const
00311 {
00312 T norm(0.0);
00313 for (size_type j=0; j<colsize(); j++)
00314 {
00315 T sum(0.0);
00316 for (size_type i=0; i<rowsize(); i++)
00317 sum += myabs((*this)[i][j]);
00318 if (sum>norm) norm = sum;
00319 }
00320 return norm;
00321 }
00322
00324 size_type rowsize () const
00325 {
00326 return m;
00327 }
00328
00330 size_type colsize () const
00331 {
00332 return n;
00333 }
00334
00336 int iwidth () const
00337 {
00338 return iwidth_;
00339 }
00340
00342 int width () const
00343 {
00344 return width_;
00345 }
00346
00348 int precision () const
00349 {
00350 return precision_;
00351 }
00352
00354 void iwidth (int i) const
00355 {
00356 iwidth_=i;
00357 }
00358
00360 void width (int i) const
00361 {
00362 width_=i;
00363 }
00364
00366 void precision (int i) const
00367 {
00368 precision_=i;
00369 }
00370
00371 private:
00372 T myabs (T x) const
00373 {
00374 if (x>=T(0)) return x; else return -x;
00375 }
00376
00377 CP<ArrayType> base;
00378 size_type m,n;
00379 size_type stride;
00380 T* data;
00381 static int iwidth_, width_, precision_;
00382 };
00383
00384 template<class T>
00385 int Matrix<T>::iwidth_ = 3;
00386 template<class T>
00387 int Matrix<T>::width_ = 10;
00388 template<class T>
00389 int Matrix<T>::precision_ = 2;
00390
00392 template <class T>
00393 inline std::ostream& operator<< (std::ostream& s, const Matrix<T>& A)
00394 {
00395 s << " " << std::setw(A.iwidth()) << " " << " ";
00396 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00397 s << std::setw(A.width()) << j << " ";
00398 s << std::endl;
00399 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00400 {
00401 s << " " << std::setw(A.iwidth()) << i << " ";
00402 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00403 s << std::setw(A.width()) << std::scientific << std::showpoint
00404 << std::setprecision(A.precision()) << A[i][j] << " ";
00405 s << std::endl;
00406 }
00407 return s;
00408 }
00409
00411 template<class T>
00412 inline void fill (Matrix<T> A, const T& t)
00413 {
00414 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00415 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00416 A[i][j] = t;
00417 }
00418
00420 template<class T>
00421 inline void zero (Matrix<T> A)
00422 {
00423 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00424 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00425 A[i][j] = T(0);
00426 }
00427
00429 template<class T>
00430 inline void identity (Matrix<T> A)
00431 {
00432 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00433 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00434 if (i==j)
00435 A[i][i] = T(1);
00436 else
00437 A[i][j] = T(0);
00438 }
00439
00441 template<class T>
00442 inline void spd (Matrix<T> A)
00443 {
00444 if (A.rowsize()!=A.colsize() || A.rowsize()==0)
00445 HDNUM_ERROR("need square and nonempty matrix");
00446 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00447 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00448 if (i==j)
00449 A[i][i] = T(4.0);
00450 else
00451 A[i][j] = - T(1.0)/((i-j)*(i-j));
00452 }
00453
00455 template<class T>
00456 inline void vandermonde (Matrix<T> A, const Vector<T> x)
00457 {
00458 if (A.rowsize()!=A.colsize() || A.rowsize()==0)
00459 HDNUM_ERROR("need square and nonempty matrix");
00460 if (A.rowsize()!=x.size())
00461 HDNUM_ERROR("need A and x of same size");
00462 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00463 {
00464 T p(1.0);
00465 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00466 {
00467 A[i][j] = p;
00468 p *= x[i];
00469 }
00470 }
00471 }
00472
00474 template<class T>
00475 inline Matrix<T> copy (const Matrix<T> A)
00476 {
00477 Matrix<T> B(A.rowsize(),A.colsize());
00478 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00479 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00480 B[i][j] = A[i][j];
00481 return B;
00482 }
00483
00485 template<class T>
00486 inline void gnuplot (const std::string& fname, const Matrix<T> A)
00487 {
00488 std::fstream f(fname.c_str(),std::ios::out);
00489 for (typename Matrix<T>::size_type i=0; i<A.rowsize(); ++i)
00490 {
00491 for (typename Matrix<T>::size_type j=0; j<A.colsize(); ++j)
00492 f << std::setw(A.width()) << std::scientific << std::showpoint
00493 << std::setprecision(A.precision()) << A[i][j] << std::endl;
00494 f << std::endl;
00495 }
00496 f.close();
00497 }
00498
00499
00500 }
00501
00502 #endif