Blender  V2.59
cmat.h
Go to the documentation of this file.
00001 
00005 /*
00006 
00007 *
00008 * Template Numerical Toolkit (TNT): Linear Algebra Module
00009 *
00010 * Mathematical and Computational Sciences Division
00011 * National Institute of Technology,
00012 * Gaithersburg, MD USA
00013 *
00014 *
00015 * This software was developed at the National Institute of Standards and
00016 * Technology (NIST) by employees of the Federal Government in the course
00017 * of their official duties. Pursuant to title 17 Section 105 of the
00018 * United States Code, this software is not subject to copyright protection
00019 * and is in the public domain.  The Template Numerical Toolkit (TNT) is
00020 * an experimental system.  NIST assumes no responsibility whatsoever for
00021 * its use by other parties, and makes no guarantees, expressed or implied,
00022 * about its quality, reliability, or any other characteristic.
00023 *
00024 * BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
00025 * see http://math.nist.gov/tnt for latest updates.
00026 *
00027 */
00028 
00029 
00030 
00031 // C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing
00032 //
00033 
00034 #ifndef CMAT_H
00035 #define CMAT_H
00036 
00037 #include "subscript.h"
00038 #include "vec.h"
00039 #include <stdlib.h>
00040 #include <assert.h>
00041 #include <iostream>
00042 #ifdef TNT_USE_REGIONS
00043 #include "region2d.h"
00044 #endif
00045 
00046 namespace TNT
00047 {
00048 
00049 template <class T>
00050 class Matrix 
00051 {
00052 
00053 
00054   public:
00055 
00056     typedef Subscript   size_type;
00057     typedef         T   value_type;
00058     typedef         T   element_type;
00059     typedef         T*  pointer;
00060     typedef         T*  iterator;
00061     typedef         T&  reference;
00062     typedef const   T*  const_iterator;
00063     typedef const   T&  const_reference;
00064 
00065     Subscript lbound() const { return 1;}
00066  
00067   protected:
00068     Subscript m_;
00069     Subscript n_;
00070     Subscript mn_;      // total size
00071     T* v_;                  
00072     T** row_;           
00073     T* vm1_ ;       // these point to the same data, but are 1-based 
00074     T** rowm1_;
00075 
00076     // internal helper function to create the array
00077     // of row pointers
00078 
00079     void initialize(Subscript M, Subscript N)
00080     {
00081         mn_ = M*N;
00082         m_ = M;
00083         n_ = N;
00084 
00085         v_ = new T[mn_]; 
00086         row_ = new T*[M];
00087         rowm1_ = new T*[M];
00088 
00089         assert(v_  != NULL);
00090         assert(row_  != NULL);
00091         assert(rowm1_ != NULL);
00092 
00093         T* p = v_;              
00094         vm1_ = v_ - 1;
00095         for (Subscript i=0; i<M; i++)
00096         {
00097             row_[i] = p;
00098             rowm1_[i] = p-1;
00099             p += N ;
00100             
00101         }
00102 
00103         rowm1_ -- ;     // compensate for 1-based offset
00104     }
00105    
00106     void copy(const T*  v)
00107     {
00108         Subscript N = m_ * n_;
00109         Subscript i;
00110 
00111 #ifdef TNT_UNROLL_LOOPS
00112         Subscript Nmod4 = N & 3;
00113         Subscript N4 = N - Nmod4;
00114 
00115         for (i=0; i<N4; i+=4)
00116         {
00117             v_[i] = v[i];
00118             v_[i+1] = v[i+1];
00119             v_[i+2] = v[i+2];
00120             v_[i+3] = v[i+3];
00121         }
00122 
00123         for (i=N4; i< N; i++)
00124             v_[i] = v[i];
00125 #else
00126 
00127         for (i=0; i< N; i++)
00128             v_[i] = v[i];
00129 #endif      
00130     }
00131 
00132     void set(const T& val)
00133     {
00134         Subscript N = m_ * n_;
00135         Subscript i;
00136 
00137 #ifdef TNT_UNROLL_LOOPS
00138         Subscript Nmod4 = N & 3;
00139         Subscript N4 = N - Nmod4;
00140 
00141         for (i=0; i<N4; i+=4)
00142         {
00143             v_[i] = val;
00144             v_[i+1] = val;
00145             v_[i+2] = val;
00146             v_[i+3] = val; 
00147         }
00148 
00149         for (i=N4; i< N; i++)
00150             v_[i] = val;
00151 #else
00152 
00153         for (i=0; i< N; i++)
00154             v_[i] = val;
00155         
00156 #endif      
00157     }
00158     
00159 
00160     
00161     void destroy()
00162     {     
00163         /* do nothing, if no memory has been previously allocated */
00164         if (v_ == NULL) return ;
00165 
00166         /* if we are here, then matrix was previously allocated */
00167         if (v_ != NULL) delete [] (v_);     
00168         if (row_ != NULL) delete [] (row_);
00169 
00170         /* return rowm1_ back to original value */
00171         rowm1_ ++;
00172         if (rowm1_ != NULL ) delete [] (rowm1_);
00173     }
00174 
00175 
00176   public:
00177 
00178     operator T**(){ return  row_; }
00179     operator T**() const { return row_; }
00180 
00181 
00182     Subscript size() const { return mn_; }
00183 
00184     // constructors
00185 
00186     Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
00187 
00188     Matrix(const Matrix<T> &A)
00189     {
00190         initialize(A.m_, A.n_);
00191         copy(A.v_);
00192     }
00193 
00194     Matrix(Subscript M, Subscript N, const T& value = T())
00195     {
00196         initialize(M,N);
00197         set(value);
00198     }
00199 
00200     Matrix(Subscript M, Subscript N, const T* v)
00201     {
00202         initialize(M,N);
00203         copy(v);
00204     }
00205 
00206 
00207     // destructor
00208     //
00209     ~Matrix()
00210     {
00211         destroy();
00212     }
00213 
00214 
00215     // reallocating
00216     //
00217     Matrix<T>& newsize(Subscript M, Subscript N)
00218     {
00219         if (num_rows() == M && num_cols() == N)
00220             return *this;
00221 
00222         destroy();
00223         initialize(M,N);
00224         
00225         return *this;
00226     }
00227 
00228                 void
00229         diagonal(Vector<T> &diag)
00230         {
00231                 int sz = diag.dim();
00232                 newsize(sz,sz);
00233                 set(0);
00234 
00235                 Subscript i;
00236                 for (i = 0; i < sz; i++) {
00237                         row_[i][i] = diag[i];
00238                 }
00239         }
00240 
00241 
00242 
00243     // assignments
00244     //
00245     Matrix<T>& operator=(const Matrix<T> &A)
00246     {
00247         if (v_ == A.v_)
00248             return *this;
00249 
00250         if (m_ == A.m_  && n_ == A.n_)      // no need to re-alloc
00251             copy(A.v_);
00252 
00253         else
00254         {
00255             destroy();
00256             initialize(A.m_, A.n_);
00257             copy(A.v_);
00258         }
00259 
00260         return *this;
00261     }
00262         
00263     Matrix<T>& operator=(const T& scalar)
00264     { 
00265         set(scalar); 
00266         return *this;
00267     }
00268 
00269 
00270     Subscript dim(Subscript d) const 
00271     {
00272 #ifdef TNT_BOUNDS_CHECK
00273        assert( d >= 1);
00274         assert( d <= 2);
00275 #endif
00276         return (d==1) ? m_ : ((d==2) ? n_ : 0); 
00277     }
00278 
00279     Subscript num_rows() const { return m_; }
00280     Subscript num_cols() const { return n_; }
00281 
00282 
00283 
00284 
00285     inline T* operator[](Subscript i)
00286     {
00287 #ifdef TNT_BOUNDS_CHECK
00288         assert(0<=i);
00289         assert(i < m_) ;
00290 #endif
00291         return row_[i];
00292     }
00293 
00294     inline const T* operator[](Subscript i) const
00295     {
00296 #ifdef TNT_BOUNDS_CHECK
00297         assert(0<=i);
00298         assert(i < m_) ;
00299 #endif
00300         return row_[i];
00301     }
00302 
00303     inline reference operator()(Subscript i)
00304     { 
00305 #ifdef TNT_BOUNDS_CHECK
00306         assert(1<=i);
00307         assert(i <= mn_) ;
00308 #endif
00309         return vm1_[i]; 
00310     }
00311 
00312     inline const_reference operator()(Subscript i) const
00313     { 
00314 #ifdef TNT_BOUNDS_CHECK
00315         assert(1<=i);
00316         assert(i <= mn_) ;
00317 #endif
00318         return vm1_[i]; 
00319     }
00320 
00321 
00322 
00323     inline reference operator()(Subscript i, Subscript j)
00324     { 
00325 #ifdef TNT_BOUNDS_CHECK
00326         assert(1<=i);
00327         assert(i <= m_) ;
00328         assert(1<=j);
00329         assert(j <= n_);
00330 #endif
00331         return  rowm1_[i][j]; 
00332     }
00333 
00334 
00335     
00336     inline const_reference operator() (Subscript i, Subscript j) const
00337     {
00338 #ifdef TNT_BOUNDS_CHECK
00339         assert(1<=i);
00340         assert(i <= m_) ;
00341         assert(1<=j);
00342         assert(j <= n_);
00343 #endif
00344         return rowm1_[i][j]; 
00345     }
00346 
00347 
00348 
00349 #ifdef TNT_USE_REGIONS
00350 
00351     typedef Region2D<Matrix<T> > Region;
00352     
00353 
00354     Region operator()(const Index1D &I, const Index1D &J)
00355     {
00356         return Region(*this, I,J);
00357     }
00358 
00359 
00360     typedef const_Region2D< Matrix<T> > const_Region;
00361     const_Region operator()(const Index1D &I, const Index1D &J) const
00362     {
00363         return const_Region(*this, I,J);
00364     }
00365 
00366 #endif
00367 
00368 
00369 };
00370 
00371 
00372 /* ***************************  I/O  ********************************/
00373 
00374 template <class T>
00375 std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
00376 {
00377     Subscript M=A.num_rows();
00378     Subscript N=A.num_cols();
00379 
00380     s << M << " " << N << "\n";
00381 
00382     for (Subscript i=0; i<M; i++)
00383     {
00384         for (Subscript j=0; j<N; j++)
00385         {
00386             s << A[i][j] << " ";
00387         }
00388         s << "\n";
00389     }
00390 
00391 
00392     return s;
00393 }
00394 
00395 template <class T>
00396 std::istream& operator>>(std::istream &s, Matrix<T> &A)
00397 {
00398 
00399     Subscript M, N;
00400 
00401     s >> M >> N;
00402 
00403     if ( !(M == A.num_rows() && N == A.num_cols() ))
00404     {
00405         A.newsize(M,N);
00406     }
00407 
00408 
00409     for (Subscript i=0; i<M; i++)
00410         for (Subscript j=0; j<N; j++)
00411         {
00412             s >>  A[i][j];
00413         }
00414 
00415 
00416     return s;
00417 }
00418 
00419 // *******************[ basic matrix algorithms ]***************************
00420 
00421 template <class T>
00422 Matrix<T> operator+(const Matrix<T> &A, 
00423     const Matrix<T> &B)
00424 {
00425     Subscript M = A.num_rows();
00426     Subscript N = A.num_cols();
00427 
00428     assert(M==B.num_rows());
00429     assert(N==B.num_cols());
00430 
00431     Matrix<T> tmp(M,N);
00432     Subscript i,j;
00433 
00434     for (i=0; i<M; i++)
00435         for (j=0; j<N; j++)
00436             tmp[i][j] = A[i][j] + B[i][j];
00437 
00438     return tmp;
00439 }
00440 
00441 template <class T>
00442 Matrix<T> operator-(const Matrix<T> &A, 
00443     const Matrix<T> &B)
00444 {
00445     Subscript M = A.num_rows();
00446     Subscript N = A.num_cols();
00447 
00448     assert(M==B.num_rows());
00449     assert(N==B.num_cols());
00450 
00451     Matrix<T> tmp(M,N);
00452     Subscript i,j;
00453 
00454     for (i=0; i<M; i++)
00455         for (j=0; j<N; j++)
00456             tmp[i][j] = A[i][j] - B[i][j];
00457 
00458     return tmp;
00459 }
00460 
00461 template <class T>
00462 Matrix<T> mult_element(const Matrix<T> &A, 
00463     const Matrix<T> &B)
00464 {
00465     Subscript M = A.num_rows();
00466     Subscript N = A.num_cols();
00467 
00468     assert(M==B.num_rows());
00469     assert(N==B.num_cols());
00470 
00471     Matrix<T> tmp(M,N);
00472     Subscript i,j;
00473 
00474     for (i=0; i<M; i++)
00475         for (j=0; j<N; j++)
00476             tmp[i][j] = A[i][j] * B[i][j];
00477 
00478     return tmp;
00479 }
00480 
00481 template <class T>
00482 void transpose(const Matrix<T> &A, Matrix<T> &S)
00483 {
00484     Subscript M = A.num_rows();
00485     Subscript N = A.num_cols();
00486 
00487     assert(M==S.num_cols());
00488     assert(N==S.num_rows());
00489 
00490     Subscript i, j;
00491 
00492     for (i=0; i<M; i++)
00493         for (j=0; j<N; j++)
00494             S[j][i] = A[i][j];
00495 
00496 }
00497 
00498 
00499 template <class T>
00500 inline void matmult(Matrix<T>& C, const Matrix<T>  &A, 
00501     const Matrix<T> &B)
00502 {
00503 
00504     assert(A.num_cols() == B.num_rows());
00505 
00506     Subscript M = A.num_rows();
00507     Subscript N = A.num_cols();
00508     Subscript K = B.num_cols();
00509 
00510     C.newsize(M,K);
00511 
00512     T sum;
00513 
00514     const T* row_i;
00515     const T* col_k;
00516 
00517     for (Subscript i=0; i<M; i++)
00518     for (Subscript k=0; k<K; k++)
00519     {
00520         row_i  = &(A[i][0]);
00521         col_k  = &(B[0][k]);
00522         sum = 0;
00523         for (Subscript j=0; j<N; j++)
00524         {
00525             sum  += *row_i * *col_k;
00526             row_i++;
00527             col_k += K;
00528         }
00529         C[i][k] = sum; 
00530     }
00531 
00532 }
00533 
00534 template <class T>
00535 void matmult(Vector<T> &y, const Matrix<T>  &A, const Vector<T> &x)
00536 {
00537 
00538 #ifdef TNT_BOUNDS_CHECK
00539     assert(A.num_cols() == x.dim());
00540         assert(A.num_rows() == y.dim());
00541 #endif
00542 
00543     Subscript M = A.num_rows();
00544     Subscript N = A.num_cols();
00545 
00546     T sum;
00547 
00548     for (Subscript i=0; i<M; i++)
00549     {
00550         sum = 0;
00551         const T* rowi = A[i];
00552         for (Subscript j=0; j<N; j++)
00553             sum = sum +  rowi[j] * x[j];
00554 
00555         y[i] = sum; 
00556     }
00557 }
00558 
00559 template <class T>
00560 inline void matmultdiag(
00561         Matrix<T>& C, 
00562         const Matrix<T> &A, 
00563     const Vector<T> &diag
00564 ){
00565 #ifdef TNT_BOUNDS_CHECK
00566     assert(A.num_cols() ==A.num_rows()== diag.dim());
00567 #endif
00568 
00569     Subscript M = A.num_rows();
00570     Subscript K = diag.dim();
00571 
00572     C.newsize(M,K);
00573 
00574     const T* row_i;
00575     const T* col_k;
00576 
00577     for (Subscript i=0; i<M; i++) {
00578                 for (Subscript k=0; k<K; k++)
00579                 {
00580                         C[i][k] = A[i][k] * diag[k];            
00581                 }
00582         }
00583 }
00584         
00585 
00586 template <class T>
00587 inline void matmultdiag(
00588         Matrix<T>& C, 
00589     const Vector<T> &diag,
00590         const Matrix<T> &A 
00591 ){
00592 #ifdef TNT_BOUNDS_CHECK
00593     assert(A.num_cols() ==A.num_rows()== diag.dim());
00594 #endif
00595 
00596     Subscript M = A.num_rows();
00597     Subscript K = diag.dim();
00598 
00599     C.newsize(M,K);
00600 
00601     for (Subscript i=0; i<M; i++) {
00602         
00603                 const T diag_element = diag[i];
00604 
00605                 for (Subscript k=0; k<K; k++)
00606                 {
00607                         C[i][k] = A[i][k] * diag_element;               
00608                 }
00609         }
00610 }
00611 
00612 } // namespace TNT
00613 
00614 #endif // CMAT_H
00615