00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef GENLIB2_MATRIX_INCLUDED
00022 #define GENLIB2_MATRIX_INCLUDED
00023
00024 #include <cassert>
00025 #include <iostream>
00026 #include <cmath>
00027 using namespace std;
00028
00029
00030
00031
00032 namespace GenLib2
00033 {
00034
00039 template <class T>
00040 class Matrix
00041 {
00042
00043
00044
00045 protected:
00049
00050 void allocate(int m, int n);
00051
00053 void free();
00054
00056 void copy(const T* v);
00057
00059 void set(const T& val);
00061
00062
00063
00064
00065 public:
00069
00070 Matrix();
00071
00073 Matrix(int m, int n, const T& val=T(0));
00074
00076 Matrix(int m, int n, const T* v);
00077
00079 Matrix(int m, const T& val=T(0));
00080
00082 Matrix(int m, const T* v);
00083
00084
00085
00086
00088 Matrix(const Matrix& A);
00090
00092 ~Matrix();
00093
00097
00098 Matrix& operator=(const Matrix& A);
00099
00101 Matrix& copy(int rl, int cl, const Matrix& A);
00102
00108 Matrix& newsize(int m, int n=1);
00109
00111 Matrix& clear() { set(T(0)); return *this; }
00112
00114 Matrix& null() { set(T(0)); return *this; }
00115
00117 void set_diagonal();
00118
00123 void identity(T val=T(1));
00124
00126 Matrix& set_all(const T& val);
00127
00128
00129
00130
00131
00132
00133
00134 void get_col(int c, Matrix& col);
00135
00136
00137
00139 void make_upper_symmetric();
00140
00142 void make_lower_symmetric();
00144
00148
00149 int rows() const { return _m; }
00150
00152 int cols() const { return _n; }
00153
00155 int size() const { return _m * _n; }
00156
00158 bool is_data() const { return (_data != 0); }
00159
00161 bool is_row() const { return (_row != 0); }
00162
00164 T& elem(int i, int j) const { return _row[i][j]; }
00165
00167 void elem(int i, int j, T val) { _row[i][j] = val; }
00168
00170 T& operator()(int i, int j) { return _row[i][j]; }
00171
00173 const T& operator()(int i, int j) const { return _row[i][j]; }
00174
00176 T& operator()(int i) { return _row[i][0]; }
00177
00179 const T& operator()(int i) const { return _row[i][0]; }
00180
00182 T* row(int i) const { return _row[i]; }
00183
00184
00185
00186
00187
00188
00189
00190
00192
00196
00197 void read(std::istream& is);
00198
00200 void print(ostream& os) const;
00201
00203 void print_symb(ostream& os, char zero=' ', char nozero='*') const;
00204
00206 void print_pbm(ostream& os) const;
00208
00212
00213 Matrix& operator*=(T s);
00214
00216 Matrix& operator/=(T s);
00218
00233 void tred2(Matrix& d, Matrix& e);
00234
00252 bool tqli(Matrix& d, Matrix& e, int maxIter=30);
00253
00265 bool eigensystem(Matrix& eigen_vals, Matrix& eigen_vecs);
00267
00268 protected:
00270 int _m;
00271
00273 int _n;
00274
00276 T* _data;
00277
00279 T** _row;
00280 };
00281
00282
00283
00284
00285
00286
00288 template <class T>
00289 istream& operator>>(istream& is, Matrix<T>& m);
00290
00292 template <class T>
00293 ostream& operator<<(ostream& os, const Matrix<T>& m);
00294
00295
00296
00297
00299 template <class T>
00300 Matrix<T> transpose(const Matrix<T>& A);
00301
00302
00303
00304
00305
00307 template <class T>
00308 Matrix<T> operator+(const Matrix<T>& A, const Matrix<T>& B);
00309
00311 template<class T>
00312 Matrix<T> operator-(const Matrix<T>& A, const Matrix<T>& B);
00313
00315 template <class T>
00316 void mult(Matrix<T>& C, const Matrix<T>& A, const Matrix<T>& B, bool clr=true);
00317
00319 template <class T>
00320 Matrix<T> mult(const Matrix<T>& A, const Matrix<T>& B);
00321
00323 template <class T>
00324 Matrix<T> operator*(const Matrix<T>& A, const Matrix<T>& B);
00325
00327
00328
00329
00330
00331
00332
00333
00334 template <class T>
00335 void mult_gen(Matrix<T>& C, bool clr, const Matrix<T>& A, bool atr,
00336 const Matrix<T>& B, bool btr);
00337
00339 template <class T>
00340 Matrix<T> operator*(double s, const Matrix<T>& A);
00341
00342
00343
00344
00345
00346
00347 template <class T>
00348 void Matrix<T>::allocate(int m, int n)
00349 {
00350 assert(_data == 0);
00351 assert(_row == 0);
00352
00353 assert(m >= 0 && n >= 0);
00354
00355 _m = m;
00356 _n = n;
00357
00358 if (_m != 0 && _n != 0)
00359 {
00360
00361 _data = (T*)new T[_m * _n];
00362 assert(_data != 0);
00363
00364
00365 _row = new T*[_m];
00366 assert(_row != 0);
00367
00368
00369 _row[0] = _data;
00370 for (register int i = 1; i < _m; i++)
00371 _row[i] = _row[i-1] + _n;
00372 }
00373 }
00374
00375
00376
00377
00378 template <class T>
00379 void Matrix<T>::free()
00380 {
00381
00382 if (_data == 0) return;
00383
00384
00385 if (_data != 0) delete[] _data;
00386
00387
00388 if (_row != 0) delete[] _row;
00389
00390 _data = 0;
00391 _row = 0;
00392 }
00393
00394
00395
00396
00397 template <class T>
00398 void Matrix<T>::copy(const T* v)
00399 {
00400
00401 for (int i = 0; i < _m * _n; i++)
00402 _data[i] = v[i];
00403 }
00404
00405
00406
00407
00408 template <class T>
00409 void Matrix<T>::set(const T& val)
00410 {
00411
00412 if (_data == 0) return;
00413 for (int i = 0; i < _m * _n; i++)
00414 _data[i] = val;
00415 }
00416
00417
00418
00419
00420 template <class T>
00421 Matrix<T>::Matrix() : _m(0), _n(0), _data(0), _row(0) {}
00422
00423
00424
00425
00426 template <class T>
00427 Matrix<T>::Matrix(int m, int n, const T& val) : _m(0), _n(0),
00428 _data(0), _row(0)
00429 {
00430 allocate(m, n);
00431 set(val);
00432 }
00433
00434
00435
00436
00437 template <class T>
00438 Matrix<T>::Matrix(int m, int n, const T* v) : _m(0), _n(0),
00439 _data(0), _row(0)
00440 {
00441 allocate(m, n);
00442 copy(v);
00443
00444 }
00445
00446
00447
00448
00449 template <class T>
00450 Matrix<T>::Matrix(int m, const T& val) : _m(0), _n(0),
00451 _data(0), _row(0)
00452 {
00453 allocate(m, 1);
00454 set(val);
00455 }
00456
00457
00458
00459
00460 template <class T>
00461 Matrix<T>::Matrix(int m, const T* v) : _m(0), _n(0),
00462 _data(0), _row(0)
00463 {
00464 allocate(m, 1);
00465 copy(v);
00466
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 template <class T>
00497 Matrix<T>::Matrix(const Matrix& A) : _m(0), _n(0),
00498 _data(0), _row(0)
00499 {
00500 allocate(A._m, A._n);
00501 copy(A._data);
00502 }
00503
00504
00505
00506
00507 template <class T>
00508 Matrix<T>::~Matrix()
00509 {
00510 free();
00511 }
00512
00513
00514
00515
00516
00517 template <class T>
00518 Matrix<T>& Matrix<T>::newsize(int m, int n)
00519 {
00520 if (_m == m && _n == n) return *this;
00521 free();
00522 allocate(m, n);
00523 return *this;
00524 }
00525
00526
00527
00528
00529 template <class T>
00530 Matrix<T>& Matrix<T>::operator=(const Matrix& A)
00531 {
00532 if (_data == A._data) return *this;
00533
00534 if (_m == A._m && _n == A._n)
00535 copy(A._data);
00536 else
00537 {
00538 newsize(A._m, A._n);
00539 copy(A._data);
00540
00541
00542 }
00543
00544 return *this;
00545 }
00546
00547
00548
00549
00550 template <class T>
00551 Matrix<T>& Matrix<T>::copy(int rl, int cl, const Matrix<T>& A)
00552 {
00553
00554 assert(0 <= rl);
00555 assert(rl < _m);
00556 assert(0 <= cl);
00557 assert(cl < _n);
00558
00559 assert(rl+A._m < _m);
00560 assert(cl+A._n < _n);
00561
00562 for (int i = 0; i < A._m; i++)
00563 for (int j = 0; j < A._n; j++)
00564 _row[rl+i][cl+j] = A._row[i][j];
00565
00566 return *this;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585 template <class T>
00586 void Matrix<T>::set_diagonal()
00587 {
00588 register int i = _n < _m ? _n : _m;
00589
00590 for(i -= 1; i >= 0; --i)
00591 _row[i][i] = T(1);
00592 }
00593
00594
00595
00596
00597 template <class T>
00598 void Matrix<T>::identity(T val)
00599 {
00600 assert(_n == _m);
00601
00602 set(T(0));
00603 for(int i = 0; i < _m; i++)
00604 _row[i][i] = val;
00605 }
00606
00607
00608
00609
00610 template <class T>
00611 Matrix<T>& Matrix<T>::set_all(const T& val)
00612 {
00613 set(val);
00614 return *this;
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 template <class T>
00634 void Matrix<T>::get_col(int c, Matrix<T>& col)
00635 {
00636 col.newsize(_n);
00637
00638 for (int i = 0; i < _n; i++)
00639 col._row[i][0] = _row[i][c];
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 template <class T>
00674 void Matrix<T>::make_upper_symmetric()
00675 {
00676
00677 register int r, c;
00678
00679
00680 assert(_m == _n);
00681
00682 for(r = 0; r < _m; r++)
00683 for(c = r; c < _n; c++)
00684 _row[c][r] = _row[r][c];
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 }
00699
00700
00701
00702
00703 template <class T>
00704 void Matrix<T>::make_lower_symmetric()
00705 {
00706
00707 register int r, c;
00708
00709
00710 assert(_m == _n);
00711
00712 for(r = 0; r < _m; r++)
00713 for(c = r; c < _n; c++)
00714 _row[r][c] = _row[c][r];
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 }
00729
00730
00731
00732
00733 template <class T>
00734 void Matrix<T>::read(istream& is)
00735 {
00736 int m = 0, n = 0;
00737 is >> m >> n;
00738 newsize(m, n);
00739
00740 for (int i = 0; i < m; i++)
00741 for (int j = 0; j < n; j++)
00742 is >> _row[i][j];
00743 }
00744
00745
00746
00747
00748 template <class T>
00749 void Matrix<T>::print(ostream& os) const
00750 {
00751 os << _m << " " << _n << endl;
00752 for (int i = 0; i < _m; i++)
00753 {
00754 for (int j = 0; j < _n; j++)
00755 os << _row[i][j] << " ";
00756 os << endl;
00757 }
00758 }
00759
00760
00761
00762
00763 template <class T>
00764 void Matrix<T>::print_symb(ostream& os, char zero, char nozero) const
00765 {
00766 int r, c;
00767
00768
00769 os << _m << " x " << _n << ":" << endl;
00770
00771
00772 for (r = 0; r < _m; r++)
00773 {
00774 for(c = 0; c < _n; c++)
00775
00776 if (_row[r][c] == (T)0)
00777 os << zero;
00778 else
00779 os << nozero;
00780 os << endl;
00781 }
00782 }
00783
00784
00785
00786
00787 template <class T>
00788 void Matrix<T>::print_pbm(ostream& os) const
00789 {
00790 int r, c;
00791
00792
00793 os << "P1\n" << _n << " " << _m << "\n" << endl;
00794
00795
00796
00797 for (r = 0; r < _m; r++)
00798 {
00799 for(c = 0; c < _n; c++)
00800
00801 if (_row[r][c] == (T)0)
00802 os << "0 ";
00803 else
00804 os << "1 ";
00805 os << endl;
00806 }
00807 }
00808
00809
00810
00811
00812 template <class T>
00813 Matrix<T>& Matrix<T>::operator*=(T s)
00814 {
00815 for (int i = 0; i < _n; i++)
00816 for (int j = 0; j < _m; j++)
00817 _data[i][j] *= s;
00818 return *this;
00819 }
00820
00821
00822
00823
00824 template <class T>
00825 Matrix<T>& Matrix<T>::operator/=(T s)
00826 {
00827 for (int i = 0; i < _n; i++)
00828 for (int j = 0; j < _m; j++)
00829 _data[i][j] /= s;
00830 return *this;
00831 }
00832
00833
00834
00835
00836
00837 template <class T>
00838 void Matrix<T>::tred2(Matrix<T>& d, Matrix<T>& e)
00839 {
00840 int l, k, j, i;
00841 T scale, hh, h, g, f;
00842
00843
00844 assert((_n == _m) && (d.rows() >= _n) && (e.rows() >= _n));
00845
00846
00847 for (i = _n - 1; i >= 1; --i)
00848 {
00849 l = i - 1;
00850 h = scale = 0.0;
00851 if (l > 0)
00852 {
00853 for (k = 0; k <= l; ++k) scale += (T)fabs((*this)(i,k));
00854 if(scale == 0.0)
00855 e(i) = (*this)(i,l);
00856 else
00857 {
00858 for (k = 0; k <= l; ++k)
00859 {
00860 T tmp;
00861 tmp = ((*this)(i,k) /= scale);
00862 h += tmp * tmp;
00863 }
00864 f = (*this)(i,l);
00865 g = (f > 0) ? -(T)sqrt((double)h) : (T)sqrt((double)h);
00866 e(i) = scale * g;
00867 h -= f * g;
00868 (*this)(i,l) = f - g;
00869 f = 0.0;
00870 for (j = 0; j <= l; ++j)
00871 {
00872 (*this)(j,i)=(*this)(i,j) / h;
00873 g = 0.0;
00874 for (k = 0; k <= j; ++k) g += (*this)(j,k) * (*this)(i,k);
00875 for (k = j + 1; k <= l; ++k) g += (*this)(k,j) * (*this)(i,k);
00876 e(j) = g / h;
00877 f += e(j) * (*this)(i,j);
00878 }
00879 hh = f / (h + h);
00880 for(j = 0; j <= l; ++j)
00881 {
00882 f = (*this)(i,j);
00883 g = (e(j) -= hh * f);
00884 for (k = 0; k <= j; ++k) (*this)(j,k) -= (f * e(k) + g * (*this)(i,k));
00885 }
00886 }
00887 }
00888 else
00889 e(i) = (*this)(i,l);
00890
00891 d(i) = h;
00892 }
00893
00894 d(0) = e(0) = (T)0.0;
00895 for(i=0; i<_n; ++i)
00896 {
00897 l = i - 1;
00898 if (d(i) != 0.0)
00899 {
00900 for (j = 0; j <= l; ++j)
00901 {
00902 g = 0.0;
00903 for(k=0; k<=l; ++k) g += (*this)(i,k) * (*this)(k,j);
00904 for(k=0; k<=l; ++k) (*this)(k,j) -= g * (*this)(k,i);
00905 }
00906 }
00907 d(i) = (*this)(i,i);
00908 (*this)(i,i) = (T)1.0;
00909 for (j = 0; j <= l; j++) (*this)(j,i) = (*this)(i,j) = 0.0;
00910 }
00911 }
00912
00913
00914
00915
00916 template <class T>
00917 bool Matrix<T>::tqli(Matrix<T>& d, Matrix<T>& e, int maxIter)
00918 {
00919 int m, l, iter, i, k;
00920 T s, r, p, g, f, dd, c, b;
00921
00922
00923 assert(_n == _m && _n == d.rows() && _n == e.rows());
00924
00925
00926 for (i = 1; i < _n; ++i) e(i-1) = e(i);
00927 e(_n-1) = (T)0.0;
00928 for (l = 0; l < _n; ++l)
00929 {
00930 iter = 0;
00931 do
00932 {
00933 for (m = l; m < _n - 1; ++m)
00934 {
00935 dd = fabs(d(m)) + fabs(d(m+1));
00936 if ((T)(fabs(e(m)) + dd) == dd) break;
00937 }
00938 if (m != l)
00939 {
00940 if (iter++ == maxIter)
00941 {
00942 cerr << "Matrix<...>::tqli: maxIter exceeded" << endl;
00943 return false;
00944 }
00945 g = (d(l+1) - d(l)) / (2.0 * e(l));
00946 r = (T)sqrt((g * g) + 1.0);
00947 g = (T)(d(m) - d(l) + e(l) /(g + ((g < 0.0)? -fabs(r) : fabs(r))));
00948 s = c = (T)1.0;
00949 p = (T)0.0;
00950 for (i = m - 1; i >= l; --i)
00951 {
00952 f = s * e(i);
00953 b = c * e(i);
00954 if (fabs(f) >= fabs(g))
00955 {
00956 c = g / f;
00957 r = (T)sqrt(c * c + 1.0);
00958 e(i+1) = f * r;
00959 c *= (s = 1.0 / r);
00960 }
00961 else
00962 {
00963 s = f / g;
00964 r = (T)sqrt(s * s + 1.0);
00965 e(i+1) = g * r;
00966 s *= (c = 1.0 / r);
00967 }
00968 g = d(i+1) - p;
00969 r = (d(i) - g) * s + 2.0 * c * b;
00970 p = s * r;
00971 d(i+1) = g + p;
00972 g = c * r - b;
00973 for (k = 0; k < _n; ++k)
00974 {
00975 f = (*this)(k,i+1);
00976 (*this)(k,i+1) = s * (*this)(k,i) + c * f;
00977 (*this)(k,i) = c * (*this)(k,i) - s * f;
00978 }
00979 }
00980 d(l) = d(l) - p;
00981 e(l) = g;
00982 e(m) = (T)0.;
00983 }
00984 }
00985 while (m != l);
00986 }
00987
00988 return true;
00989 }
00990
00991
00992
00993
00994 template <class T>
00995 bool Matrix<T>::eigensystem(Matrix<T> &eigenVals, Matrix<T> &eigenVects)
00996 {
00997 Matrix<T> e(_n);
00998
00999
01000 assert(_n == _m
01001 && eigenVals.rows() == _n && eigenVals.cols() == 1
01002 && eigenVects.rows() == _n && eigenVects.cols() == _n);
01003
01004
01005 eigenVects = (*this);
01006 eigenVects.tred2(eigenVals, e);
01007
01008
01009 return(eigenVects.tqli(eigenVals, e));
01010 }
01011
01012
01013
01014
01015
01016
01017 template <class T>
01018 istream& operator>>(istream& is, Matrix<T>& m)
01019 {
01020 m.read(is);
01021 return is;
01022 }
01023
01024 template <class T>
01025 ostream& operator<<(ostream& os, const Matrix<T>& m)
01026 {
01027 m.print(os);
01028 return os;
01029 }
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 template <class T>
01040 Matrix<T> transpose(const Matrix<T>& A)
01041 {
01042 int m = A.rows();
01043 int n = A.cols();
01044
01045 Matrix<T> B(n, m);
01046
01047 for (register int i = 0; i < m; i++)
01048 for (register int j = 0; j < n; j++)
01049 B(j,i) = A(i,j);
01050
01051 return B;
01052 }
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093 template <class T>
01094 Matrix<T> operator+(const Matrix<T>& A, const Matrix<T>& B)
01095 {
01096 int m = A.rows();
01097 int n = A.cols();
01098
01099 assert(m == B.rows());
01100 assert(n == B.cols());
01101
01102 Matrix<T> C(m, n);
01103
01104 for (register int i = 0; i < m; i++)
01105 for (register int j = 0; j < n; j++)
01106 C(i,j) = A(i,j) + B(i,j);
01107
01108 return C;
01109 }
01110
01111
01112
01113
01114 template <class T>
01115 Matrix<T> operator-(const Matrix<T>& A, const Matrix<T>& B)
01116 {
01117 int m = A.rows();
01118 int n = A.cols();
01119
01120 assert(m == B.rows());
01121 assert(n == B.cols());
01122
01123 Matrix<T> C(m, n);
01124
01125 for (register int i = 0; i < m; i++)
01126 for (register int j = 0; j < n; j++)
01127 C(i,j) = A(i,j) - B(i,j);
01128
01129 return C;
01130 }
01131
01132
01133
01134
01135
01136 template <class T>
01137 void mult(Matrix<T>& C, const Matrix<T>& A, const Matrix<T>& B, bool clr)
01138 {
01139 int m = A.rows();
01140 int n = A.cols();
01141 int o = B.rows();
01142 int p = B.cols();
01143
01144
01145 assert(n == o);
01146
01147
01148 C.newsize(m, p);
01149
01150
01151 if (clr) C.clear();
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173 for (register int i = 0; i < m; ++i)
01174 for (register int j = 0; j < p; ++j)
01175 {
01176 register T sum = (T)0;
01177
01178 for (register int k = 0; k < n; ++k)
01179 {
01180 sum += A(i,k) * B(k,j);
01181 }
01182
01183 C(i,j) += sum;
01184 }
01185 }
01186
01187
01188
01189
01190 template <class T>
01191 Matrix<T> mult(const Matrix<T>& A, const Matrix<T>& B)
01192 {
01193 Matrix<T> C;
01194 mult(C, A, B, true);
01195 return C;
01196 }
01197
01198
01199
01200
01201 template <class T>
01202 Matrix<T> operator*(const Matrix<T>& A, const Matrix<T>& B)
01203 {
01204 return mult(A,B);
01205 }
01206
01207
01208
01209
01210 template <class T>
01211 void mult_gen(Matrix<T>& C, bool clr, const Matrix<T>& A, bool atr,
01212 const Matrix<T>& B, bool btr)
01213 {
01214
01215 int pa = atr ? A.rows() : A.cols();
01216 int pb = btr ? B.cols() : B.rows();
01217 assert(pa == pb);
01218
01219
01220 int n = atr ? A.cols() : A.rows();
01221 int m = btr ? B.rows() : B.cols();
01222
01223
01224 C.newsize(n, m);
01225
01226
01227 if (clr) C.clear();
01228
01229
01230 for (register int i = 0; i < n; ++i)
01231 for (register int j = 0; j < m; ++j)
01232 {
01233 register T sum = (T)0;
01234
01235 for (register int k = 0; k < pa; ++k)
01236 {
01237 register T av = atr ? A(k,i) : A(i,k);
01238 register T bv = btr ? B(j,k) : B(k,j);
01239 sum += av * bv;
01240 }
01241
01242 C(i,j) += sum;
01243 }
01244 }
01245
01246
01247
01248
01249 template <class T>
01250 Matrix<T> operator*(double s, const Matrix<T>& A)
01251 {
01252 int m = A.rows();
01253 int n = A.cols();
01254
01255 Matrix<T> C(m, n);
01256
01257 for (register int i = 0; i < m; i++)
01258 for (register int j = 0; j < n; j++)
01259 C(i,j) = s * A(i,j);
01260
01261 return C;
01262 }
01263
01264 }
01265
01266 #endif