00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef MATVEC_MATRIX_H
00023 #define MATVEC_MATRIX_H
00024
00025 #include <string>
00026 #include <fstream>
00027 #include <cassert>
00028 #include "session.h"
00029 #include "vector.h"
00030
00031
00032 namespace matvec {
00033
00034
00035
00036
00037
00038
00039
00040
00041 template<class T> class Matrix {
00042
00043 public:
00044 typedef int size_type;
00045 typedef T value_type;
00046 typedef T element_type;
00047 typedef T* pointer;
00048 typedef T* iterator;
00049 typedef T& reference;
00050 typedef const T* const_iterator;
00051 typedef const T* const_pointer;
00052 typedef const T& const_reference;
00053 typedef std::reverse_iterator<iterator>reverse_iterator;
00054 typedef std::reverse_iterator<const_iterator>const_reverse_iterator;
00055
00056 enum orientation {ROW,COLUMN};
00057
00058 Matrix(void) {
00059
00060 initialize(0,0,0);
00061 }
00062 Matrix(const size_type m,const size_type n) {
00063
00064 initialize(m,n,0);
00065 }
00066 Matrix(const size_type m,const size_type n,const T** a) {
00067
00068 initialize(m,n,a);
00069 }
00070 Matrix(const Matrix& a){
00071
00072 initialize(a.nrow,a.ncol,(const T**)a.me);
00073 }
00074
00075 T** begin(void) { return me; }
00076 const T** begin(void) const { return (const T**)me; }
00077
00078 virtual ~Matrix(void){clear();}
00079
00080 void copy(const Matrix &a);
00081 Matrix& assign(const Matrix &a) {copy(a); return *this;}
00082 Matrix& assign(const T &x);
00083
00084 Matrix& resize(const size_type n,const size_type m, const T &val = T());
00085 Matrix& resize(const size_type n,const size_type m, const T *a);
00086 Matrix& resize(const Matrix& a){resize(a.ne); return *this;}
00087 Matrix& reserve(const size_type n,const size_type m);
00088
00089 Matrix& operator = (const Matrix &a) { return assign(a); }
00090 Matrix& operator = (const T &x) { return assign(x); }
00091
00092 Matrix operator + (const Matrix &a) const;
00093 Matrix operator - (const Matrix &a) const;
00094 Matrix operator * (const Matrix &a) const;
00095 Matrix operator / (const Matrix &a) const;
00096
00097 Vector<T> operator * (const Vector<T> &a) const;
00098
00099 Matrix operator + (const T& x) const;
00100 Matrix operator - (const T& x) const;
00101 Matrix operator * (const T& x) const;
00102 Matrix operator / (const T& x) const;
00103
00104 Matrix& operator += (const Matrix& a);
00105 Matrix& operator -= (const Matrix& a);
00106 Matrix& operator *= (const Matrix& a);
00107 Matrix& operator /= (const Matrix& a);
00108 Matrix& operator += (const T& x);
00109 Matrix& operator -= (const T& x);
00110 Matrix& operator *= (const T& x);
00111 Matrix& operator /= (const T& x);
00112
00113 T* operator [] (const size_type i) { return me[i]; }
00114 const T* operator [] (const size_type i) const { return me[i]; }
00115 T& operator () (const size_type i,const size_type j);
00116 Matrix operator - (void) const;
00117 Matrix& operator + (void) { return *this; }
00118
00119 Matrix<bool> operator ! (void) const;
00120
00121 Matrix<bool> operator == (const Matrix &a) const;
00122 Matrix<bool> operator < (const Matrix &a) const;
00123 Matrix<bool> operator > (const Matrix &a) const;
00124 Matrix<bool> operator != (const Matrix &a) const;
00125 Matrix<bool> operator <= (const Matrix &a) const;
00126 Matrix<bool> operator >= (const Matrix &a) const;
00127
00128 Matrix<bool> operator == (const T &x) const;
00129 Matrix<bool> operator < (const T &x) const;
00130 Matrix<bool> operator > (const T &x) const;
00131 Matrix<bool> operator != (const T &x) const;
00132 Matrix<bool> operator <= (const T &x) const;
00133 Matrix<bool> operator >= (const T &x) const;
00134
00135 bool all(void) const;
00136 bool any(void) const;
00137 bool symmetric(void) const;
00138 bool empty(void) const { return (nrow == 0 || ncol == 0); }
00139 bool save(const std::string &fname,const int io_mode = std::ios::out) const;
00140
00141 Matrix apply(T (*f)(T)) const;
00142 Matrix apply(T (*f)(T,T),const Matrix &b) const;
00143 Matrix apply(T (*f)(T,T),const T &b) const;
00144 Matrix submat(const size_type idx1,const size_type idx2, const int len1 = 0, const int len2 = 0) const;
00145 Matrix submat(const Matrix<bool>& a) const;
00146 Matrix transpose(void) const;
00147 Matrix kron(const Matrix &b) const;
00148 Matrix reshape(const size_type m,const size_type n,orientation orient = COLUMN) const;
00149 Matrix diag(void) const;
00150 Vector<T> diag(const size_type k) const;
00151 Vector<T> vec(orientation orient = COLUMN) const;
00152 Vector<T> sum(orientation orient = COLUMN) const;
00153 Vector<T> sumsq(orientation orient = COLUMN) const;
00154 Vector<T> max(orientation orient = COLUMN) const;
00155 Vector<T> min(orientation orient = COLUMN) const;
00156 virtual std::ostream& print(std::ostream &os = std::cout) const;
00157 T trace(T init = T()) const;
00158 T& at(const size_type i,const size_type j);
00159
00160 Matrix& sortby(orientation orient,const size_type k);
00161 int size(void) const { return nrow*ncol; }
00162 int num_rows(void) const { return nrow; }
00163 int num_cols(void) const { return ncol; }
00164 void clear(void);
00165 void input(const std::string &fname,
00166 const size_type m,
00167 const size_type n);
00168
00169
00170 T **me;
00171 int nrow,ncol;
00172
00173 void initialize(const size_type m,const size_type n,const T **a);
00174 };
00175
00176 template<class T> inline void Matrix<T>::initialize(const size_type m,const size_type n,const T **a)
00177 {
00178 if (m == 0 || n == 0) {
00179 nrow = 0; ncol = 0; me = 0;
00180 } else {
00181 nrow = m; ncol = n;
00182 me = new T* [nrow];
00183 assert( me != 0 );
00184 for (int j,i=0; i<nrow; ++i) {
00185 me[i] = new T [ncol];
00186 assert( me[i] != 0 );
00187 if (a) {
00188 for (j=0; j<ncol; ++j) me[i][j] = a[i][j];
00189 } else {
00190 for (j=0; j<ncol; ++j) me[i][j] = T();
00191 }
00192 }
00193 }
00194 return;
00195 }
00196
00197 template<class T> inline T& Matrix<T>::at(const size_type i,const size_type j)
00198 {
00199 if (i < 0 || i >= nrow || j < 0 || j >= ncol) throw exception("Matrix<T>::at(): out of range");
00200 return me[i][j];
00201 }
00202
00203 template<class T> inline void Matrix<T>::clear(void)
00204 {
00205 if (me) {
00206 for (int i=0; i<nrow; ++i) delete [] me[i];
00207 delete [] me;
00208 me = 0;
00209 }
00210 nrow = 0;
00211 ncol = 0;
00212 }
00213
00214 template<class T> inline void Matrix<T>::input(const std::string &fname,
00215 const size_type m,
00216 const size_type n)
00217 {
00218 resize(m,n);
00219 std::ifstream infile(fname.c_str(),std::ios::in);
00220 if (!infile) {
00221 std::cerr << fname << ": cannot open\n";
00222 } else {
00223 for (int j,i=0; i<m; ++i) for (j=0; j<n; ++j) infile >> me[i][j];
00224 infile.close();
00225 }
00226 return;
00227 }
00228
00229 template<class T> inline void Matrix<T>::copy(const Matrix<T> & a)
00230 {
00231 if (this == &a) return;
00232 reserve(a.nrow,a.ncol);
00233
00234
00235 for (int i=0; i<nrow; ++i) {
00236 for (int j=0; j<ncol; j++){
00237 me[i][j] = a.me[i][j];
00238 }
00239 }
00240 return;
00241 }
00242
00243 template<class T> inline Matrix<T>& Matrix<T>::assign(const T& a)
00244 {
00245 if (me) {
00246 resize(nrow,ncol,a);
00247 } else {
00248 resize(1,1,a);
00249 }
00250 return *this;
00251 }
00252
00253 template<class T> inline Matrix<T>& Matrix<T>::reserve(const size_type m,const size_type n)
00254 {
00255 if (m != nrow || n != ncol) {
00256 clear();
00257 nrow = m;
00258 ncol = n;
00259 if(nrow>0){
00260 me = new T* [nrow];
00261 }
00262 else {
00263 me = 0;
00264 return *this;
00265 }
00266 assert( me != 0 );
00267 for (int i=0; i<nrow; ++i) {
00268 if(ncol>0){
00269 me[i] = new T [ncol];
00270 }
00271 else {
00272 me[i] = 0;
00273 }
00274 assert( me[i] != 0 );
00275 }
00276 }
00277 return *this;
00278 }
00279
00280 template<class T> inline Matrix<T>& Matrix<T>::resize(const size_type m,const size_type n,const T& val)
00281 {
00282 if (m == 0 || n == 0) {
00283 clear();
00284 } else {
00285 int i,j;
00286 if (m != nrow || n != ncol) {
00287 clear();
00288 nrow = m;
00289 ncol = n;
00290 me = new T* [nrow];
00291 assert( me != 0 );
00292 for (i=0; i<nrow; ++i) {
00293 me[i] = new T [ncol];
00294 assert( me[i] != 0 );
00295 }
00296 }
00297 for (i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] = val;
00298 }
00299 return *this;
00300 }
00301
00302 template<class T> inline Matrix<T>& Matrix<T>::resize(const size_type m,const size_type n,const T *a)
00303 {
00304 if (m == 0 || n == 0) {
00305 clear();
00306 } else {
00307 int i,j;
00308 if (m != nrow || n != ncol) {
00309 clear();
00310 nrow = m;
00311 ncol = n;
00312 me = new T* [nrow];
00313 assert( me != 0 );
00314 for (i=0; i<nrow; ++i) {
00315 me[i] = new T [ncol];
00316 assert( me[i] != 0 );
00317 }
00318 }
00319 for (i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] = *a++;
00320 }
00321 return *this;
00322 }
00323
00324 template<class T> inline T& Matrix<T>::operator () (const size_type i,size_type j)
00325 {
00326 if (i < 1 || i > nrow || j < 1 || j > ncol) throw exception("Matrix<T>::operator(): out of range");
00327 return me[i-1][j-1];
00328 }
00329
00330 template<class T> inline Matrix<T>& Matrix<T>::operator += (const Matrix<T> &a)
00331 {
00332 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator+=: size not conformable");
00333 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] += a[i][j];
00334 return *this;
00335 }
00336
00337 template<class T> inline Matrix<T>& Matrix<T>::operator -= (const Matrix<T> &a)
00338 {
00339 if ( nrow != a.nrow || ncol != a.ncol ) throw exception("Matrix<T>::operator-=: size not conformable");
00340 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] -= a[i][j];
00341 return *this;
00342 }
00343
00344 template<class T> inline Matrix<T>& Matrix<T>::operator *= (const Matrix<T> &a)
00345 {
00346 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator*=: size not conformable");
00347 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] *= a[i][j];
00348 return *this;
00349 }
00350
00351 template<class T> inline Matrix<T>& Matrix<T>::operator /= (const Matrix<T> &a)
00352 {
00353 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator/=: size not conformable");
00354 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] /= a[i][j];
00355 return *this;
00356 }
00357
00358 template<class T> inline Matrix<T>& Matrix<T>::operator += (const T &s)
00359 {
00360 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] += s;
00361 return *this;
00362 }
00363
00364 template<class T> inline Matrix<T>& Matrix<T>::operator -= (const T &s)
00365 {
00366 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] -= s;
00367 return *this;
00368 }
00369
00370 template<class T> inline Matrix<T>& Matrix<T>::operator *= (const T &s)
00371 {
00372 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] *= s;
00373 return *this;
00374 }
00375
00376 template<class T> inline Matrix<T>& Matrix<T>::operator /= (const T &s)
00377 {
00378 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) me[i][j] /= s;
00379 return *this;
00380 }
00381
00382 template<class T> inline Matrix<bool> Matrix<T>::operator == (const Matrix<T> &a) const
00383 {
00384 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator==: size not conformable");
00385 Matrix<bool> temp(nrow,ncol);
00386 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] == a[i][j]);
00387 return temp;
00388 }
00389
00390 template<class T> inline Matrix<bool> Matrix<T>::operator == (const T &x) const
00391 {
00392 Matrix<bool> temp(nrow,ncol);
00393 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] == x);
00394 return temp;
00395 }
00396
00397 template<class T> inline Matrix<bool> Matrix<T>::operator < (const Matrix<T>& a) const
00398 {
00399 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator<: size not conformable");
00400 Matrix<bool> temp(nrow,ncol);
00401 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] < a[i][j]);
00402 return temp;
00403 }
00404
00405 template<class T> inline Matrix<bool> Matrix<T>::operator < (const T &x) const
00406 {
00407 Matrix<bool> temp(nrow,ncol);
00408 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] < x);
00409 return temp;
00410 }
00411
00412 template<class T> inline Matrix<bool> Matrix<T>::operator > (const Matrix<T> &a) const
00413 {
00414 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator>: size not conformable");
00415 Matrix<bool> temp(nrow,ncol);
00416 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] > a[i][j]);
00417 return temp;
00418 }
00419
00420 template<class T> inline Matrix<bool> Matrix<T>::operator > (const T &x) const
00421 {
00422 Matrix<bool> temp(nrow,ncol);
00423 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] > x);
00424 return temp;
00425 }
00426
00427 template<class T> inline Matrix<bool> Matrix<T>::operator != (const Matrix<T> &a) const
00428 {
00429 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator!=: size not conformable");
00430 Matrix<bool> temp(nrow,ncol);
00431 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] != a[i][j]);
00432 return temp;
00433 }
00434
00435 template<class T> inline Matrix<bool> Matrix<T>::operator != (const T &x) const
00436 {
00437 Matrix<bool> temp(nrow,ncol);
00438 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] != x);
00439 return temp;
00440 }
00441
00442 template<class T> inline Matrix<bool> Matrix<T>::operator <= (const Matrix<T> &a) const
00443 {
00444 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator<=: size not conformable");
00445 Matrix<bool> temp(nrow,ncol);
00446 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] <= a[i][j]);
00447 return temp;
00448 }
00449
00450 template<class T> inline Matrix<bool> Matrix<T>::operator <= (const T &x) const
00451 {
00452 Matrix<bool> temp(nrow,ncol);
00453 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] <= x);
00454 return temp;
00455 }
00456
00457
00458 template<class T> inline Matrix<bool> Matrix<T>::operator >= (const Matrix<T> &a) const
00459 {
00460 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator>=: size not conformable");
00461 Matrix<bool> temp(nrow,ncol);
00462 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] >= a[i][j]);
00463 return temp;
00464 }
00465
00466 template<class T> inline Matrix<bool> Matrix<T>::operator >= (const T &x) const
00467 {
00468 Matrix<bool> temp(nrow,ncol);
00469 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (me[i][j] >= x);
00470 return temp;
00471 }
00472
00473 template<class T> inline Matrix<T> Matrix<T>::operator + (const Matrix<T> &a) const
00474 {
00475 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator+: size not conformable");
00476 Matrix<T> temp(nrow,ncol);
00477 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = me[i][j] + a.me[i][j];
00478 return temp;
00479 }
00480
00481 template<class T> inline Matrix<T> Matrix<T>::operator - (const Matrix<T> &a) const
00482 {
00483 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator-: size not conformable");
00484 Matrix<T> temp(nrow,ncol);
00485 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = me[i][j] - a.me[i][j];
00486 return temp;
00487 }
00488
00489 template<class T> inline Matrix<T> Matrix<T>::operator * (const Matrix<T> &a) const
00490 {
00491 if (ncol != a.nrow) throw exception("Matrix<T>::operator*: size not conformable");
00492 Matrix<T> temp(nrow,a.ncol);
00493 T x;
00494 for (int t,j,i=0; i<nrow; ++i) {
00495 for (j=0; j<a.ncol; ++j) {
00496 x = T();
00497 for (t=0; t<ncol; ++t) x += me[i][t]*a[t][j];
00498 temp[i][j] = x;
00499 }
00500 }
00501 return temp;
00502 }
00503
00504 template<class T> inline Vector<T> Matrix<T>::operator * (const Vector<T> &a) const
00505 {
00506 if (ncol != a.size()) throw exception("Matrix<T>::operator*: size not conformable");
00507 Vector<T> temp(nrow);
00508 T x;
00509 for (int j,i=0; i<nrow; ++i) {
00510 x = T();
00511 for (j=0; j<ncol; ++j) x += me[i][j]*a[j];
00512 temp[i] = x;
00513 }
00514 return temp;
00515 }
00516
00517 template<class T> inline Matrix<T> Matrix<T>::operator / (const Matrix<T> &a) const
00518 {
00519 if (nrow != a.nrow || ncol != a.ncol) throw exception("Matrix<T>::operator/: size not conformable");
00520 Matrix<T> temp(nrow,ncol);
00521 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = me[i][j] / a.me[i][j];
00522 return temp;
00523 }
00524
00525
00526 template<class T> inline Matrix<T> Matrix<T>::operator + (const T &a) const
00527 {
00528 Matrix<T> temp(nrow,ncol);
00529 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = me[i][j] + a;
00530 return temp;
00531 }
00532
00533 template<class T> inline Matrix<T> Matrix<T>::operator - (const T &a) const
00534 {
00535 Matrix<T> temp(nrow,ncol);
00536 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = me[i][j] - a;
00537 return temp;
00538 }
00539
00540 template<class T> inline Matrix<T> Matrix<T>::operator * (const T &a) const
00541 {
00542 Matrix<T> temp(nrow,ncol);
00543 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = me[i][j] * a;
00544 return temp;
00545 }
00546
00547 template<class T> inline Matrix<T> Matrix<T>::operator / (const T &a) const
00548 {
00549 Matrix<T> temp(nrow,ncol);
00550 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = me[i][j] / a;
00551 return temp;
00552 }
00553
00554 template<class T> inline Matrix<T> Matrix<T>::operator - (void) const
00555 {
00556 Matrix<T> temp(nrow,ncol);
00557 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = - me[i][j];
00558 return temp;
00559 }
00560
00561 template<class T> inline Matrix<bool> Matrix<T>::operator ! (void) const
00562 {
00563 Matrix<bool> temp(nrow,ncol);
00564 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = ! me[i][j];
00565 return temp;
00566 }
00567
00568 template<class T> inline bool Matrix<T>::all(void) const
00569 {
00570 if (!me) return false;
00571 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) if (me[i][j] == false) return false;
00572 return true;
00573 }
00574
00575 template<class T> inline bool Matrix<T>::any(void) const
00576 {
00577 if (!me) return false;
00578 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) if (me[i][j] == true) return true;
00579 return false;
00580 }
00581
00582 template<class T> inline bool Matrix<T>::symmetric(void) const
00583 {
00584 if (!me) return false;
00585 for (int j,i=1; i<nrow; ++i) for (j=0; j<i; ++j) if (me[i][j] != me[j][i]) return false;
00586 return true;
00587 }
00588
00589 template<class T> inline bool Matrix<T>::save(const std::string &fname,const int io_mode) const
00590 {
00591 std::ofstream ofs(fname.c_str(),(OpenModeType)io_mode);
00592 if (ofs) {
00593 print(ofs);
00594 ofs.close();
00595 } else {
00596 std::cerr << fname << ": cannot open\n";
00597 }
00598 return true;
00599 }
00600
00601 template<class T> inline T Matrix<T>::trace(T init) const
00602 {
00603 int n = std::min(nrow,ncol);
00604 for (int i=0; i<n; ++i) init += me[i][i];
00605 return init;
00606 }
00607
00608 template<class T> inline Matrix<T> Matrix<T>::apply(T (*f)(T)) const
00609 {
00610 Matrix<T> temp(nrow,ncol);
00611 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (*f)(me[i][j]);
00612 return temp;
00613 }
00614
00615 template<class T> inline Matrix<T> Matrix<T>::apply(T (*f)(T,T),const Matrix &b) const
00616 {
00617 if (nrow != b.nrow || ncol != b.ncol) throw exception("Matrix<T>::apply(): size not conformable");
00618 Matrix<T> temp(nrow,ncol);
00619 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (*f)(me[i][j],b[i][j]);
00620 return temp;
00621 }
00622
00623 template<class T> inline Matrix<T> Matrix<T>::apply(T (*f)(T,T),const T &b) const
00624 {
00625 Matrix<T> temp(nrow,ncol);
00626 for (int j,i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[i][j] = (*f)(me[i][j],b);
00627 return temp;
00628 }
00629
00630 template<class T> inline Matrix<T> Matrix<T>::submat(const size_type idx1,const size_type idx2, const int len1, const int len2) const
00631 {
00632 int ir,ic,i,j,t,k;
00633 if (len1 == 0) {
00634 ir = nrow - 1;
00635 } else {
00636 ir = idx1 + len1 - 1;
00637 }
00638 if (len2 == 0) {
00639 ic = ncol - 1;
00640 } else {
00641 ic = idx2 + len2 - 1;
00642 }
00643 Matrix<T> temp(len1,len2);
00644 for (i=idx1; i<= ir; ++i) {
00645 t = i - idx1;
00646 for (j=idx2; j<=ic; ++j) {
00647 k = j - idx2;
00648 temp[t][k] = me[i][j];
00649 }
00650 }
00651 return temp;
00652 }
00653
00654 template<class T> inline Matrix<T> Matrix<T>::submat(const Matrix<bool> &v) const
00655 {
00656 int n = 0;
00657
00658
00659
00660
00661
00662 Matrix<T> temp(n);
00663
00664
00665
00666 return temp;
00667 }
00668
00669 template<class T> inline Matrix<T> Matrix<T>::transpose(void) const
00670 {
00671 Matrix<T> temp(ncol,nrow);
00672 for (int j,i=0; i<ncol; ++i) for (j=0; j<nrow; ++j) temp[i][j] = me[j][i];
00673 return temp;
00674 }
00675
00676 template<class T> inline Matrix<T> Matrix<T>::kron(const Matrix<T> &b) const
00677 {
00678 Matrix<T> temp(nrow*b.nrow,ncol*b.ncol);
00679 int i,j,k,t,ii,iii,jj,jjj;
00680 for (i=0; i<nrow; ++i) {
00681 ii = i*b.nrow;
00682 for (j=0; j<ncol; ++j) {
00683 jj = j*b.ncol;
00684 iii = ii;
00685 for (k=0; k<b.nrow; ++k) {
00686 jjj = jj;
00687 for (t=0; t<b.ncol; ++t) temp[iii][jjj++] = me[i][j]*b[k][t];
00688 iii++;
00689 }
00690 }
00691 }
00692 return temp;
00693 }
00694
00695 template<class T> inline Matrix<T> Matrix<T>::reshape(const size_type m,const size_type n,orientation orient) const
00696 {
00697 Matrix<T> temp(m,n);
00698 int i,j,t,k;
00699 if (orient == ROW) {
00700 for (t=0,k=0,i=0; i<m; ++i) for (j=0; j<n; ++j) {
00701 if (k >= ncol) {
00702 t++;
00703 if (t >= nrow) return temp;
00704 k = 0;
00705 }
00706 temp[i][j] = me[t][k++];
00707 }
00708 } else if (orient == COLUMN) {
00709 for (t=0,k=0,i=0; i<m; ++i) for (j=0; j<n; ++j) {
00710 if (t >= nrow) {
00711 k++;
00712 if (k >= ncol) return temp;
00713 t = 0;
00714 }
00715 temp[i][j] = me[t++][k];
00716 }
00717 } else {
00718 std::cerr << "unknow orientation\n";
00719 exit(1);
00720 }
00721 return temp;
00722 }
00723
00724 template<class T> inline Matrix<T> Matrix<T>::diag(void) const
00725 {
00726 int n = std::min(nrow,ncol);
00727 Matrix<T> temp(n,n);
00728 for (int i=0; i<n; ++i) temp[i][i] = me[i][i];
00729 return temp;
00730 }
00731
00732 template<class T> inline Vector<T> Matrix<T>::diag(const size_type k) const
00733 {
00734 int i,n = std::min(nrow,ncol) - std::abs(k);
00735 Vector<T> temp(n);
00736 if (k >= 0) {
00737 for (i=0; i<n; i++) temp[i] = me[i][i+k];
00738 } else {
00739 for (i=0; i<n; i++) temp[i] = me[i-k][i];
00740 }
00741 return temp;
00742 }
00743
00744 template<class T> inline Vector<T> Matrix<T>::vec(orientation orient) const
00745 {
00746 Vector<T> temp;
00747 if (!me) return temp;
00748 temp.reserve(nrow*ncol);
00749 int i,j,t=0;
00750 if (orient == ROW) {
00751 for (i=0; i<nrow; ++i) for (j=0; j<ncol; ++j) temp[t++] = me[i][j];
00752 } else if (orient == COLUMN) {
00753 for (j=0; j<ncol; ++j) for (i=0; i<nrow; ++i) temp[t++] = me[i][j];
00754 } else {
00755 std::cerr << "unknow orientation\n";
00756 exit(1);
00757 }
00758 return temp;
00759 }
00760
00761 template<class T> inline Vector<T> Matrix<T>::sum(orientation orient) const
00762 {
00763 Vector<T> temp;
00764 if (!me) return temp;
00765 int i,j;
00766 T init;
00767 if (orient == ROW) {
00768 temp.reserve(nrow);
00769 for (i=0; i<nrow; ++i) {
00770 init = T();
00771 for (j=0; j<ncol; ++j) init += me[i][j];
00772 temp[i] = init;
00773 }
00774 } else if (orient == COLUMN) {
00775 temp.reserve(ncol);
00776 for (j=0; j<ncol; ++j) {
00777 init = T();
00778 for (i=0; i<nrow; ++i) init += me[i][j];
00779 temp[j] = init;
00780 }
00781 } else {
00782 std::cerr << "unknow orientation\n";
00783 exit(1);
00784 }
00785 return temp;
00786 }
00787
00788 template<class T> inline Vector<T> Matrix<T>::sumsq(orientation orient) const
00789 {
00790 Vector<T> temp;
00791 if (!me) return temp;
00792 int i,j;
00793 T init;
00794 if (orient == ROW) {
00795 temp.reserve(nrow);
00796 for (i=0; i<nrow; ++i) {
00797 init = T();
00798 for (j=0; j<ncol; ++j) init += me[i][j]*me[i][j];
00799 temp[i] = init;
00800 }
00801 } else if (orient == COLUMN) {
00802 temp.reserve(ncol);
00803 for (j=0; j<ncol; ++j) {
00804 init = T();
00805 for (i=0; i<nrow; ++i) init += me[i][j]*me[i][j];
00806 temp[j] = init;
00807 }
00808 } else {
00809 std::cerr << "unknow orientation\n";
00810 exit(1);
00811 }
00812 return temp;
00813 }
00814
00815 template<class T> inline Vector<T> Matrix<T>::max(orientation orient) const
00816 {
00817 Vector<T> temp;
00818 if (!me) return temp;
00819 int i,j;
00820 if (orient == ROW) {
00821 temp.reserve(nrow);
00822 for (i=0; i<nrow; ++i) {
00823 temp[i] = me[i][0];
00824 for (j=0; j<ncol; ++j) if (me[i][j] > temp[i]) temp[i] = me[i][j];
00825 }
00826 } else if (orient == COLUMN) {
00827 temp.reserve(ncol);
00828 for (j=0; j<ncol; ++j) {
00829 temp[j] = me[0][j];
00830 for (i=0; i<nrow; ++i) if (me[i][j] > temp[j]) temp[j] = me[i][j];
00831 }
00832 } else {
00833 std::cerr << "unknow orientation\n";
00834 exit(1);
00835 }
00836 return temp;
00837 }
00838
00839 template<class T> inline Vector<T> Matrix<T>::min(orientation orient) const
00840 {
00841 Vector<T> temp;
00842 if (!me) return temp;
00843 int i,j;
00844 if (orient == ROW) {
00845 temp.reserve(nrow);
00846 for (i=0; i<nrow; ++i) {
00847 temp[i] = me[i][0];
00848 for (j=1; j<ncol; ++j) if (me[i][j] < temp[i]) temp[i] = me[i][j];
00849 }
00850 } else if (orient == COLUMN) {
00851 temp.reserve(ncol);
00852 for (j=0; j<ncol; ++j) {
00853 temp[j] = me[0][j];
00854 for (i=1; i<nrow; ++i) if (me[i][j] < temp[j]) temp[j] = me[i][j];
00855 }
00856 } else {
00857 std::cerr << "unknow orientation\n";
00858 exit(1);
00859 }
00860 return temp;
00861 }
00862
00863 template<class T> inline std::ostream& Matrix<T>::print(std::ostream &os) const
00864 {
00865 int i,j;
00866 for (i=0; i<nrow; ++i) {
00867 for (j=0; j<ncol; ++j) {
00868 os << ' ' ;
00869 os.width(8) ;
00870 os.precision(SESSION.output_precision) ;
00871 os << me[i][j];
00872 }
00873 os << "\n";
00874 }
00875 return os;
00876 }
00877
00878 template<class T> inline Matrix<T>& Matrix<T>::sortby(orientation orient,const size_type t)
00879 {
00880 int n = 1;
00881 Vector<int> by(n);
00882 by[0] = t;
00883
00884 int nstack = 100;
00885 int l,r,i,j,k,j1;
00886 T a1,a2;
00887 Vector<T> x(n);
00888 Matrix<int> stack(2,nstack);
00889 int s = 0;
00890 stack[s][s] = 0;
00891
00892 if (orient == COLUMN) {
00893 stack[1][0] = nrow-1;
00894 do {
00895 l = stack[0][s]; r = stack[1][s]; s -= 1;
00896 do {
00897 i = l; j = r; j1 = (l+r)/2;
00898 for (k=0; k<n; k++) x[k] = me[j1][by[k]];
00899 do {
00900 k = 0;
00901 while (k < n) {
00902 a1 = me[i][by[k]]; a2 = x[k];
00903 if (a1 < a2) {
00904 i += 1; k = 0;
00905 }
00906 else if (a1 == a2) {
00907 k += 1;
00908 }
00909 else if (a1 > a2) break;
00910 }
00911 k = 0;
00912 while (k < n) {
00913 a1 = me[j][by[k]]; a2 = x[k];
00914 if (a1 > a2) {
00915 j -= 1; k = 0;
00916 }
00917 else if (a1 == a2) {
00918 k += 1;
00919 }
00920 else if (a1 < a2) break;
00921 }
00922
00923 if (i <= j) {
00924 for (k=0; k<ncol; k++) {
00925 a1 = me[i][k];
00926 me[i][k] = me[j][k];
00927 me[j][k] = a1;
00928 }
00929 i += 1; j -= 1;
00930 }
00931 } while (i <= j);
00932 if (i < r) {
00933 s += 1;
00934 if (s >= nstack-1) {
00935 std::cerr << " NSTACK " << nstack << " too small in SORTQR\n";
00936 s = -1;
00937 break;
00938 }
00939 stack[0][s] = i; stack[1][s] = r;
00940 }
00941 r = j;
00942 } while (l < r);
00943 } while (s >= 0);
00944 } else if (orient == ROW) {
00945 stack[1][0] = ncol - 1;
00946 do {
00947 l = stack[0][s]; r = stack[1][s]; s -= 1;
00948 do {
00949 i = l; j = r; j1 = (l+r)/2;
00950 for (k=0; k<n; k++) x[k] = me[by[k]][j1];
00951 do {
00952 k = 0;
00953 while (k < n) {
00954 a1 = me[by[k]][i]; a2 = x[k];
00955 if (a1 < a2) {
00956 i += 1; k = 0;
00957 }
00958 else if (a1 == a2) {
00959 k += 1;
00960 }
00961 else if (a1 > a2) break;
00962 }
00963 k = 0;
00964 while (k < n) {
00965 a1 = me[by[k]][j]; a2 = x[k];
00966 if (a1 > a2) {
00967 j -= 1; k = 0;
00968 }
00969 else if (a1 == a2) {
00970 k += 1;
00971 }
00972 else if (a1 < a2) break;
00973 }
00974 if (i <= j) {
00975 for (k=0; k<nrow; k++) {
00976 a1 = me[k][i];
00977 me[k][i] = me[k][j];
00978 me[k][j] = a1;
00979 }
00980 i += 1; j -= 1;
00981 }
00982 } while (i <= j);
00983 if (i < r) {
00984 s += 1;
00985 if (s >= nstack-1) {
00986 std::cerr << " NSTACK " << nstack << " too small in SORTQR\n";
00987 s = -1;
00988 break;
00989 }
00990 stack[0][s] = i; stack[1][s] = r;
00991 }
00992 r = j;
00993 } while (l < r);
00994 } while (s >= 0);
00995 } else {
00996 std::cerr << "unknow orientation\n";
00997 exit(1);
00998 }
00999 return *this;
01000 }
01001
01002
01003
01004
01005 template<class T> inline Matrix<T> operator / (const T &a,const Matrix<T> &b)
01006 {
01007 Matrix<T> temp(b.num_rows(),b.num_cols());
01008 for (int j,i=0; i<b.num_rows(); ++i) for (j=0; j<b.num_cols(); ++j) temp[i][j] = a/b[i][j];
01009 return temp;
01010 }
01011
01012 template<class T> inline Vector<T> operator * (const Vector<T> &a,const Matrix<T> &b)
01013 {
01014 if (a.size() != b.num_rows()) throw exception("Matrix<T>::operator*: size not conformable");
01015 Vector<T> temp(b.num_cols());
01016 T** me = b.begin();
01017 T x;
01018 for (int i,j=0; j<b.num_cols(); ++j) {
01019 x = T();
01020 for (i=0; i<b.num_rows(); ++i) x += a[i] * me[i][j];
01021 temp[j] = x;
01022 }
01023 return temp;
01024 }
01025
01026 template<class T> inline Matrix<T> hadjoin (const Matrix<T> &a,const Matrix<T> &b)
01027 {
01028 if (a.num_rows() != b.num_rows()) throw exception("Matrix<T>::hadjoin(): size not conformable");
01029 Matrix<T> temp(a.num_rows(),a.num_cols() + b.num_cols());
01030 for (int i=0; i<a.num_rows(); ++i) {
01031 memcpy(temp[i],a[i],sizeof(T)*a.num_cols());
01032 memcpy(&(temp[i][a.num_cols()]),b[i],sizeof(T)*b.num_cols());
01033 }
01034 return temp;
01035 }
01036
01037 template<class T> inline Matrix<T> hadjoin (const Matrix<T> &a,const Vector<T> &b)
01038 {
01039 if (a.num_rows() != b.size()) throw exception("Matrix<T>::hadjoin(): size not conformable");
01040 Matrix<T> temp(a.num_rows(),a.num_cols() + 1);
01041 for (int i=0; i<a.num_rows(); ++i) {
01042 memcpy(temp[i],a[i],sizeof(T)*a.num_cols());
01043 temp[i][a.num_cols()] = b[i];
01044 }
01045 return temp;
01046 }
01047
01048 template<class T> inline Matrix<T> hadjoin (const Vector<T> &a,const Matrix<T> &b)
01049 {
01050 if (a.size() != b.num_rows()) throw exception("Matrix<T>::hadjoin(): size not conformable");
01051 Matrix<T> temp(a.size(),1 + b.num_cols());
01052 for (int i=0; i<a.size(); ++i) {
01053 temp[i][0] = a[i];
01054 memcpy(&(temp[i][1]),b[i],sizeof(T)*b.num_cols());
01055 }
01056 return temp;
01057 }
01058
01059 template<class T> inline Matrix<T> vadjoin (const Matrix<T> &a,const Matrix<T> &b)
01060 {
01061 if (a.num_cols() != b.num_cols()) throw exception("Matrix<T>::vadjoin(): size not conformable");
01062 Matrix<T> temp(a.num_rows() + b.num_rows(),a.num_cols());
01063 for (int i,j=0; j<a.num_cols(); ++j) {
01064 for (i=0; i<a.num_rows(); ++i) temp[i][j] = a[i][j];
01065 for (i=0; i<b.num_rows(); ++i) temp[a.num_rows() + i][j] = b[i][j];
01066 }
01067 return temp;
01068 }
01069
01070 template<class T> inline Matrix<T> vadjoin (const Matrix<T> &a,const Vector<T> &b)
01071 {
01072 if (a.num_cols() != b.size()) throw exception("Matrix<T>::vadjoin(): size not conformable");
01073 Matrix<T> temp(a.num_rows() + 1,a.num_cols());
01074 for (int i,j=0; j<a.num_cols(); ++j) {
01075 for (i=0; i<a.num_rows(); ++i) temp[i][j] = a[i][j];
01076 temp[a.num_rows()][j] = b[j];
01077 }
01078 return temp;
01079 }
01080
01081 template<class T> inline Matrix<T> vadjoin (const Vector<T> &a,const Matrix<T> &b)
01082 {
01083 if (a.size() != b.num_cols()) throw exception("Matrix<T>::vadjoin(): size not conformable");
01084 Matrix<T> temp(1 + b.num_rows(),b.num_cols());
01085 for (int i,j=0; j<b.num_cols(); ++j) {
01086 temp[0][j] = a[j];
01087 for (i=0; i<b.num_rows(); ++i) temp[1 + i][j] = b[i][j];
01088 }
01089 return temp;
01090 }
01091
01092 template<class T> inline Matrix<T> diag (const Vector<T> &a)
01093 {
01094 Matrix<T> temp(a.size(),a.size());
01095 for (int i=0; i<a.size(); ++i) temp[i][i] = a[i];
01096 return temp;
01097 }
01098
01099 template<class T> inline Matrix<T> diag (const Matrix<T> &a) { return a.diag(); }
01100
01101
01102 template<class T> Matrix<T> sin (const Matrix<T> &a) { return a.apply(std::sin); }
01103 template<class T> Matrix<T> asin (const Matrix<T> &a) { return a.apply(std::asin); }
01104 template<class T> Matrix<T> cos (const Matrix<T> &a) { return a.apply(std::cos); }
01105 template<class T> Matrix<T> acos (const Matrix<T> &a) { return a.apply(std::acos); }
01106 template<class T> Matrix<T> tan (const Matrix<T> &a) { return a.apply(std::tan); }
01107 template<class T> Matrix<T> atan (const Matrix<T> &a) { return a.apply(std::atan); }
01108 template<class T> Matrix<T> ceil (const Matrix<T> &a) { return a.apply(std::ceil); }
01109 template<class T> Matrix<T> floor(const Matrix<T> &a) { return a.apply(std::floor); }
01110 template<class T> Matrix<T> log (const Matrix<T> &a) { return a.apply(std::log); }
01111 template<class T> Matrix<T> log10(const Matrix<T> &a) { return a.apply(std::log10); }
01112 template<class T> Matrix<T> exp (const Matrix<T> &a) { return a.apply(std::exp); }
01113 template<class T> Matrix<T> sqrt (const Matrix<T> &a) { return a.apply(std::sqrt); }
01114 template<class T> Matrix<T> abs (const Matrix<T> &a) { return a.apply(std::abs); }
01115 template<class T> Matrix<T> erf (const Matrix<T> &a) { return a.apply(erf); }
01116 template<class T> Matrix<T> erfc (const Matrix<T> &a) { return a.apply(erfc); }
01117
01118 template<class T> bool all (const Matrix<T> &a) { return a.all();}
01119 template<class T> bool any (const Matrix<T> &a) { return a.any();}
01120
01121 template<class T> Matrix<T> operator + (const T &a,const Matrix<T> &b) { return b + a; }
01122 template<class T> Matrix<T> operator - (const T &a,const Matrix<T> &b) { return -b + a; }
01123 template<class T> Matrix<T> operator * (const T &a,const Matrix<T> &b) { return b * a; }
01124 template<class T> Matrix<T> operator / (const T &a,const Matrix<T> &b);
01125 template<class T> std::ostream& operator << (std::ostream &os, const Matrix<T> &a) { return a.print(os); }
01126
01127 }
01128
01129
01130 #endif