00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef TNT_MATRIX_H
00025 #define TNT_MATRIX_H
00026
00027 #include "tnt_subscript.h"
00028 #include "tnt_vector.h"
00029 #include <cstdlib>
00030 #include <cassert>
00031 #include <iostream>
00032 #include <sstream>
00033 #include <fstream>
00034
00035 namespace TNT
00036 {
00037
00038
00039
00040
00055 template <class T>
00056 class Matrix
00057 {
00058
00059 private:
00060 Subscript m_;
00061 Subscript n_;
00062 Subscript mn_;
00063 T* v_;
00064 T** row_;
00065 T* vm1_ ;
00066 T** rowm1_;
00067
00068
00069
00070
00071 void initialize(Subscript M, Subscript N)
00072 {
00073 mn_ = M*N;
00074 m_ = M;
00075 n_ = N;
00076
00077 v_ = new T[mn_];
00078 row_ = new T*[M];
00079 rowm1_ = new T*[M];
00080
00081 assert(v_ != NULL);
00082 assert(row_ != NULL);
00083 assert(rowm1_ != NULL);
00084
00085 T* p = v_;
00086 vm1_ = v_ - 1;
00087 for (Subscript i=0; i<M; i++)
00088 {
00089 row_[i] = p;
00090 rowm1_[i] = p-1;
00091 p += N ;
00092
00093 }
00094
00095 rowm1_ -- ;
00096 }
00097
00098 void copy(const T* v)
00099 {
00100 Subscript N = m_ * n_;
00101 Subscript i;
00102
00103 #ifdef TNT_UNROLL_LOOPS
00104 Subscript Nmod4 = N & 3;
00105 Subscript N4 = N - Nmod4;
00106
00107 for (i=0; i<N4; i+=4)
00108 {
00109 v_[i] = v[i];
00110 v_[i+1] = v[i+1];
00111 v_[i+2] = v[i+2];
00112 v_[i+3] = v[i+3];
00113 }
00114
00115 for (i=N4; i< N; i++)
00116 v_[i] = v[i];
00117 #else
00118
00119 for (i=0; i< N; i++)
00120 v_[i] = v[i];
00121 #endif
00122 }
00123
00124 void set(const T& val)
00125 {
00126 Subscript N = m_ * n_;
00127 Subscript i;
00128
00129 #ifdef TNT_UNROLL_LOOPS
00130 Subscript Nmod4 = N & 3;
00131 Subscript N4 = N - Nmod4;
00132
00133 for (i=0; i<N4; i+=4)
00134 {
00135 v_[i] = val;
00136 v_[i+1] = val;
00137 v_[i+2] = val;
00138 v_[i+3] = val;
00139 }
00140
00141 for (i=N4; i< N; i++)
00142 v_[i] = val;
00143 #else
00144
00145 for (i=0; i< N; i++)
00146 v_[i] = val;
00147
00148 #endif
00149 }
00150
00151
00152
00153 void destroy()
00154 {
00155
00156 if (v_ == NULL) return ;
00157
00158
00159 if (v_ != NULL) delete [] (v_);
00160 if (row_ != NULL) delete [] (row_);
00161
00162
00163 rowm1_ ++;
00164 if (rowm1_ != NULL ) delete [] (rowm1_);
00165 }
00166
00167 public:
00168
00169 typedef Subscript size_type;
00170 typedef T value_type;
00171 typedef T element_type;
00172 typedef T* pointer;
00173 typedef T* iterator;
00174 typedef T& reference;
00175 typedef const T* const_iterator;
00176 typedef const T& const_reference;
00177
00178 Subscript lbound() const { return 1;}
00179
00180
00181
00182
00183 operator T**(){ return row_; }
00184 operator const T**() const { return row_; }
00185
00186
00190 Subscript size() const { return mn_; }
00191
00192
00193
00194 Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
00195
00196 Matrix(const Matrix<T> &A)
00197 {
00198 initialize(A.m_, A.n_);
00199 copy(A.v_);
00200 }
00201
00210 Matrix(Subscript M, Subscript N, const T& value = T(0))
00211 {
00212 initialize(M,N);
00213 set(value);
00214 }
00215
00224 Matrix(Subscript M, Subscript N, const T* v)
00225 {
00226 initialize(M,N);
00227 copy(v);
00228 }
00229
00238 Matrix(Subscript M, Subscript N, const char *s)
00239 {
00240 initialize(M,N);
00241
00242 std::istringstream ins(s);
00243
00244 Subscript i, j;
00245
00246 for (i=0; i<M; i++)
00247 for (j=0; j<N; j++)
00248 ins >> row_[i][j];
00249 }
00250
00251
00252
00253 ~Matrix()
00254 {
00255 destroy();
00256 }
00257
00258
00282 Matrix<T>& newsize(Subscript M, Subscript N)
00283 {
00284 if (num_rows() == M && num_cols() == N)
00285 return *this;
00286
00287 destroy();
00288 initialize(M,N);
00289
00290 return *this;
00291 }
00292
00293
00294
00295
00303 Matrix<T>& operator=(const Matrix<T> &B)
00304 {
00305 if (v_ == B.v_)
00306 return *this;
00307
00308 if (m_ == B.m_ && n_ == B.n_)
00309 copy(B.v_);
00310
00311 else
00312 {
00313 destroy();
00314 initialize(B.m_, B.n_);
00315 copy(B.v_);
00316 }
00317
00318 return *this;
00319 }
00320
00321 Matrix<T>& operator=(const T& scalar)
00322 {
00323 set(scalar);
00324 return *this;
00325 }
00326
00327
00328 Subscript dim(Subscript d) const
00329 {
00330 #ifdef TNT_BOUNDS_CHECK
00331 assert( d >= 1);
00332 assert( d <= 2);
00333 #endif
00334 return (d==1) ? m_ : ((d==2) ? n_ : 0);
00335 }
00336
00337 Subscript num_rows() const { return m_; }
00338 Subscript num_cols() const { return n_; }
00339
00340
00341
00342
00343 inline T* operator[](Subscript i)
00344 {
00345 #ifdef TNT_BOUNDS_CHECK
00346 assert(0<=i);
00347 assert(i < m_) ;
00348 #endif
00349 return row_[i];
00350 }
00351
00352 inline const T* operator[](Subscript i) const
00353 {
00354 #ifdef TNT_BOUNDS_CHECK
00355 assert(0<=i);
00356 assert(i < m_) ;
00357 #endif
00358 return row_[i];
00359 }
00360
00361 inline reference operator()(Subscript i)
00362 {
00363 #ifdef TNT_BOUNDS_CHECK
00364 assert(1<=i);
00365 assert(i <= mn_) ;
00366 #endif
00367 return vm1_[i];
00368 }
00369
00370 inline const_reference operator()(Subscript i) const
00371 {
00372 #ifdef TNT_BOUNDS_CHECK
00373 assert(1<=i);
00374 assert(i <= mn_) ;
00375 #endif
00376 return vm1_[i];
00377 }
00378
00379
00380
00381 inline reference operator()(Subscript i, Subscript j)
00382 {
00383 #ifdef TNT_BOUNDS_CHECK
00384 assert(1<=i);
00385 assert(i <= m_) ;
00386 assert(1<=j);
00387 assert(j <= n_);
00388 #endif
00389 return rowm1_[i][j];
00390 }
00391
00392
00393
00394 inline const_reference operator() (Subscript i, Subscript j) const
00395 {
00396 #ifdef TNT_BOUNDS_CHECK
00397 assert(1<=i);
00398 assert(i <= m_) ;
00399 assert(1<=j);
00400 assert(j <= n_);
00401 #endif
00402 return rowm1_[i][j];
00403 }
00404
00405
00406
00407 Vector<T> diag() const
00408 {
00409 Subscript N = n_ < m_ ? n_ : m_;
00410 Vector<T> d(N);
00411
00412 for (int i=0; i<N; i++)
00413 d[i] = row_[i][i];
00414
00415 return d;
00416 }
00417
00418 Matrix<T> upper_triangular() const;
00419 Matrix<T> lower_triangular() const;
00420
00421
00422
00423 };
00424
00425
00426
00427
00428
00429 template <class T>
00430 std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
00431 {
00432 Subscript M=A.num_rows();
00433 Subscript N=A.num_cols();
00434
00435 for (Subscript i=0; i<M; i++)
00436 {
00437 for (Subscript j=0; j<N; j++)
00438 {
00439 s << A[i][j] << " ";
00440 }
00441 s << "\n";
00442 }
00443
00444
00445 return s;
00446 }
00447
00448
00449 template <class T>
00450 std::istream& operator>>(std::istream &s, Matrix<T> &A)
00451 {
00452
00453 Subscript M, N;
00454
00455 s >> M >> N;
00456
00457 if ( !(M == A.num_rows() && N == A.num_cols() ))
00458 {
00459 A.newsize(M,N);
00460 }
00461
00462
00463 for (Subscript i=0; i<M; i++)
00464 for (Subscript j=0; j<N; j++)
00465 {
00466 s >> A[i][j];
00467 }
00468
00469
00470 return s;
00471 }
00472
00473
00474
00475
00476
00490 template <class T>
00491 Matrix<T> & mult(Matrix<T>& C, const Matrix<T> &A, const Matrix<T> &B)
00492 {
00493
00494 #ifdef TNT_BOUNDS_CHECK
00495 assert(A.num_cols() == B.num_rows());
00496 #endif
00497
00498 Subscript M = A.num_rows();
00499 Subscript N = A.num_cols();
00500 Subscript K = B.num_cols();
00501
00502 #ifdef TNT_BOUNDS_CHECK
00503 assert(C.num_rows() == M);
00504 assert(C.num_cols() == K);
00505 #endif
00506
00507 T sum;
00508
00509 const T* row_i;
00510 const T* col_k;
00511
00512 for (Subscript i=0; i<M; i++)
00513 for (Subscript k=0; k<K; k++)
00514 {
00515 row_i = &(A[i][0]);
00516 col_k = &(B[0][k]);
00517 sum = 0;
00518 for (Subscript j=0; j<N; j++)
00519 {
00520 sum += *row_i * *col_k;
00521 row_i++;
00522 col_k += K;
00523 }
00524 C[i][k] = sum;
00525 }
00526
00527 return C;
00528 }
00529
00530
00539 template <class T>
00540 inline Matrix<T> mult(const Matrix<T> &A, const Matrix<T> &B)
00541 {
00542
00543 #ifdef TNT_BOUNDS_CHECK
00544 assert(A.num_cols() == B.num_rows());
00545 #endif
00546
00547 Subscript M = A.num_rows();
00548 Subscript N = A.num_cols();
00549 Subscript K = B.num_cols();
00550
00551 Matrix<T> tmp(M,K);
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 mult(tmp, A, B);
00566
00567 return tmp;
00568 }
00569
00578 template <class T>
00579 inline Matrix<T> operator*(const Matrix<T> &A, const Matrix<T> &B)
00580 {
00581 return mult(A,B);
00582 }
00583
00593 template <class T>
00594 inline Vector<T> mult(const Matrix<T> &A, const Vector<T> &b)
00595 {
00596
00597 #ifdef TNT_BOUNDS_CHECK
00598 assert(A.num_cols() == b.dim());
00599 #endif
00600
00601 Subscript M = A.num_rows();
00602 Subscript N = A.num_cols();
00603
00604 Vector<T> tmp(M);
00605 T sum;
00606
00607 for (Subscript i=0; i<M; i++)
00608 {
00609 sum = 0;
00610 for (Subscript j=0; j<N; j++)
00611 sum = sum + A[i][j] * b[j];
00612
00613 tmp[i] = sum;
00614 }
00615
00616 return tmp;
00617 }
00618
00628 template <class T>
00629 inline Vector<T> operator*(const Matrix<T> &A, const Vector<T> &b)
00630 {
00631 return mult(A,b);
00632 }
00633
00634
00646 template <class T>
00647 inline Matrix<T> mult(const T& s, const Matrix<T> &A)
00648 {
00649 Subscript M = A.num_rows();
00650 Subscript N = A.num_cols();
00651
00652 Matrix<T> R(M,N);
00653 for (int i=0; i<M; i++)
00654 for (int j=0; j<N; j++)
00655 R[i][j] = s * A[i][j];
00656
00657 return R;
00658 }
00659
00674 template <class T>
00675 inline Matrix<T> mult(const Matrix<T> &A, const T& s)
00676 {
00677 return mult(s, A);
00678 }
00679
00680
00693 template <class T>
00694 inline Matrix<T> mult_eq(const T& s, const Matrix<T> &A)
00695 {
00696 Subscript M = A.num_rows();
00697 Subscript N = A.num_cols();
00698
00699 for (int i=0; i<M; i++)
00700 for (int j=0; j<N; j++)
00701 A[i][j] *= s;
00702 }
00703
00704 template <class T>
00705 inline Matrix<T> mult_eq(const Matrix<T> &A, const T&a)
00706 {
00707 return mult_eq(a, A);
00708 }
00709
00710
00722 template <class T>
00723 inline Matrix<T> transpose_mult(const Matrix<T> &A, const Matrix<T> &B)
00724 {
00725
00726 #ifdef TNT_BOUNDS_CHECK
00727 assert(A.num_rows() == B.num_rows());
00728 #endif
00729
00730 Subscript M = A.num_cols();
00731 Subscript N = A.num_rows();
00732 Subscript K = B.num_cols();
00733
00734 Matrix<T> tmp(M,K);
00735 T sum;
00736
00737 for (Subscript i=0; i<N; i++)
00738 for (Subscript k=0; k<K; k++)
00739 {
00740 sum = 0;
00741 for (Subscript j=0; j<M; j++)
00742 sum = sum + A[j][i] * B[j][k];
00743
00744 tmp[i][k] = sum;
00745 }
00746
00747 return tmp;
00748 }
00749
00761 template <class T>
00762 inline Vector<T> transpose_mult(const Matrix<T> &A, const Vector<T> &b)
00763 {
00764
00765 #ifdef TNT_BOUNDS_CHECK
00766 assert(A.num_rows() == b.dim());
00767 #endif
00768
00769 Subscript M = A.num_cols();
00770 Subscript N = A.num_rows();
00771
00772 Vector<T> tmp(M);
00773
00774 for (Subscript i=0; i<M; i++)
00775 {
00776 T sum = 0;
00777 for (Subscript j=0; j<N; j++)
00778 sum = sum + A[j][i] * b[j];
00779
00780 tmp[i] = sum;
00781 }
00782
00783 return tmp;
00784 }
00785
00786
00795 template <class T>
00796 Matrix<T> add(const Matrix<T> &A, const Matrix<T> &B)
00797 {
00798 Subscript M = A.num_rows();
00799 Subscript N = A.num_cols();
00800
00801 assert(M==B.num_rows());
00802 assert(N==B.num_cols());
00803
00804 Matrix<T> tmp(M,N);
00805 Subscript i,j;
00806
00807 for (i=0; i<M; i++)
00808 for (j=0; j<N; j++)
00809 tmp[i][j] = A[i][j] + B[i][j];
00810
00811 return tmp;
00812 }
00813
00825 template <class T>
00826 inline Matrix<T> operator+(const Matrix<T> &A, const Matrix<T> &B)
00827 {
00828 return add(A,B);
00829 }
00830
00831
00832
00842 template <class T>
00843 Matrix<T>& add_eq(const Matrix<T> &A, const Matrix<T> &B)
00844 {
00845 Subscript M = A.num_rows();
00846 Subscript N = A.num_cols();
00847
00848 assert(M==B.num_rows());
00849 assert(N==B.num_cols());
00850
00851 Matrix<T> tmp(M,N);
00852 Subscript i,j;
00853
00854 for (i=0; i<M; i++)
00855 for (j=0; j<N; j++)
00856 tmp[i][j] = A[i][j] + B[i][j];
00857
00858 return A += tmp;
00859 }
00860
00872 template <class T>
00873 inline Matrix<T> operator+=(const Matrix<T> &A, const Matrix<T> &B)
00874 {
00875 return add_eq(A,B);
00876 }
00877
00887 template <class T>
00888 Matrix<T> minus(const Matrix <T>& A, const Matrix<T> &B)
00889 {
00890 Subscript M = A.num_rows();
00891 Subscript N = A.num_cols();
00892
00893 assert(M==B.num_rows());
00894 assert(N==B.num_cols());
00895
00896 Matrix<T> tmp(M,N);
00897 Subscript i,j;
00898
00899 for (i=0; i<M; i++)
00900 for (j=0; j<N; j++)
00901 tmp[i][j] = A[i][j] - B[i][j];
00902
00903 return tmp;
00904
00905 }
00906
00918 template <class T>
00919 inline Matrix<T> operator-(const Matrix<T> &A,
00920 const Matrix<T> &B)
00921 {
00922 return minus(A,B);
00923 }
00924
00925
00936 template <class T>
00937 Matrix<T> mult_element(const Matrix<T> &A, const Matrix<T> &B)
00938 {
00939 Subscript M = A.num_rows();
00940 Subscript N = A.num_cols();
00941
00942 assert(M==B.num_rows());
00943 assert(N==B.num_cols());
00944
00945 Matrix<T> tmp(M,N);
00946 Subscript i,j;
00947
00948 for (i=0; i<M; i++)
00949 for (j=0; j<N; j++)
00950 tmp[i][j] = A[i][j] * B[i][j];
00951
00952 return tmp;
00953 }
00954
00965 template <class T>
00966 Matrix<T> mult_element_eq(const Matrix<T> &A, const Matrix<T> &B)
00967 {
00968 Subscript M = A.num_rows();
00969 Subscript N = A.num_cols();
00970
00971 assert(M==B.num_rows());
00972 assert(N==B.num_cols());
00973
00974 Subscript i,j;
00975
00976 for (i=0; i<M; i++)
00977 for (j=0; j<N; j++)
00978 A[i][j] *= B[i][j];
00979
00980 }
00981
00982
00993 template <class T>
00994 double norm(const Matrix<T> &A)
00995 {
00996 Subscript M = A.num_rows();
00997 Subscript N = A.num_cols();
00998
00999 T sum = 0.0;
01000 for (int i=1; i<=M; i++)
01001 for (int j=1; j<=N; j++)
01002 sum += A(i,j) * A(i,j);
01003 return sqrt(sum);
01004
01005 }
01006
01016 template <class T>
01017 Matrix<T> transpose(const Matrix<T> &A)
01018 {
01019 Subscript M = A.num_rows();
01020 Subscript N = A.num_cols();
01021
01022 Matrix<T> S(N,M);
01023 Subscript i, j;
01024
01025 for (i=0; i<M; i++)
01026 for (j=0; j<N; j++)
01027 S[j][i] = A[i][j];
01028
01029 return S;
01030 }
01031
01032
01033
01034
01035
01036
01037
01049 template <class T>
01050 Vector<T> upper_triangular_solve(const Matrix<T> &A, const Vector<T> &b)
01051 {
01052 int n = A.num_rows() < A.num_cols() ? A.num_rows() : A.num_cols();
01053 Vector<T> x(b);
01054 for (int k=n; k >= 1; k--)
01055 {
01056 x(k) /= A(k,k);
01057 for (int i=1; i< k; i++ )
01058 x(i) -= x(k) * A(i,k);
01059 }
01060
01061 return x;
01062 }
01063
01075 template <class T>
01076 Vector<T> lower_triangular_solve(const Matrix<T> &A, const Vector<T> &b)
01077 {
01078 int n = A.num_rows() < A.num_cols() ? A.num_rows() : A.num_cols();
01079 Vector<T> x(b);
01080 for (int k=1; k <= n; k++)
01081 {
01082 x(k) /= A(k,k);
01083 for (int i=k+1; i<= n; i++ )
01084 x(i) -= x(k) * A(i,k);
01085 }
01086
01087 return x;
01088 }
01089
01090
01091
01092 }
01093
01094 #endif
01095