Blender V2.61 - r43446

tnt_cmat.h

Go to the documentation of this file.
00001 
00004 /*
00005 *
00006 * Template Numerical Toolkit (TNT)
00007 *
00008 * Mathematical and Computational Sciences Division
00009 * National Institute of Technology,
00010 * Gaithersburg, MD USA
00011 *
00012 *
00013 * This software was developed at the National Institute of Standards and
00014 * Technology (NIST) by employees of the Federal Government in the course
00015 * of their official duties. Pursuant to title 17 Section 105 of the
00016 * United States Code, this software is not subject to copyright protection
00017 * and is in the public domain. NIST assumes no responsibility whatsoever for
00018 * its use by other parties, and makes no guarantees, expressed or implied,
00019 * about its quality, reliability, or any other characteristic.
00020 *
00021 */
00022 
00023 
00024 // C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing
00025 //
00026 
00027 #ifndef TNT_CMAT_H
00028 #define TNT_CMAT_H
00029 
00030 #include "tnt_subscript.h"
00031 #include "tnt_vec.h"
00032 #include <cstdlib>
00033 #include <cassert>
00034 #include <iostream>
00035 #include <sstream>
00036 
00037 namespace TNT
00038 {
00039 
00040 
00041 template <class T>
00042 class Matrix 
00043 {
00044 
00045 
00046   public:
00047 
00048     typedef Subscript   size_type;
00049     typedef         T   value_type;
00050     typedef         T   element_type;
00051     typedef         T*  pointer;
00052     typedef         T*  iterator;
00053     typedef         T&  reference;
00054     typedef const   T*  const_iterator;
00055     typedef const   T&  const_reference;
00056 
00057     Subscript lbound() const { return 1;}
00058  
00059   protected:
00060     Subscript m_;
00061     Subscript n_;
00062     Subscript mn_;      // total size
00063     T* v_;                  
00064     T** row_;           
00065     T* vm1_ ;       // these point to the same data, but are 1-based 
00066     T** rowm1_;
00067 
00068     // internal helper function to create the array
00069     // of row pointers
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_ -- ;     // compensate for 1-based offset
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         /* do nothing, if no memory has been previously allocated */
00156         if (v_ == NULL) return ;
00157 
00158         /* if we are here, then matrix was previously allocated */
00159         if (v_ != NULL) delete [] (v_);     
00160         if (row_ != NULL) delete [] (row_);
00161 
00162         /* return rowm1_ back to original value */
00163         rowm1_ ++;
00164         if (rowm1_ != NULL ) delete [] (rowm1_);
00165     }
00166 
00167 
00168   public:
00169 
00170     operator T**(){ return  row_; }
00171     operator T**() const { return row_; }
00172 
00173 
00174     Subscript size() const { return mn_; }
00175 
00176     // constructors
00177 
00178     Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
00179 
00180     Matrix(const Matrix<T> &A)
00181     {
00182         initialize(A.m_, A.n_);
00183         copy(A.v_);
00184     }
00185 
00186     Matrix(Subscript M, Subscript N, const T& value = T())
00187     {
00188         initialize(M,N);
00189         set(value);
00190     }
00191 
00192     Matrix(Subscript M, Subscript N, const T* v)
00193     {
00194         initialize(M,N);
00195         copy(v);
00196     }
00197 
00198     Matrix(Subscript M, Subscript N, const char *s)
00199     {
00200         initialize(M,N);
00201         //std::istrstream ins(s);
00202         std::istringstream ins(s);
00203 
00204         Subscript i, j;
00205 
00206         for (i=0; i<M; i++)
00207             for (j=0; j<N; j++)
00208                 ins >> row_[i][j];
00209     }
00210 
00211     // destructor
00212     //
00213     ~Matrix()
00214     {
00215         destroy();
00216     }
00217 
00218 
00219     // reallocating
00220     //
00221     Matrix<T>& newsize(Subscript M, Subscript N)
00222     {
00223         if (num_rows() == M && num_cols() == N)
00224             return *this;
00225 
00226         destroy();
00227         initialize(M,N);
00228         
00229         return *this;
00230     }
00231 
00232 
00233 
00234 
00235     // assignments
00236     //
00237     Matrix<T>& operator=(const Matrix<T> &A)
00238     {
00239         if (v_ == A.v_)
00240             return *this;
00241 
00242         if (m_ == A.m_  && n_ == A.n_)      // no need to re-alloc
00243             copy(A.v_);
00244 
00245         else
00246         {
00247             destroy();
00248             initialize(A.m_, A.n_);
00249             copy(A.v_);
00250         }
00251 
00252         return *this;
00253     }
00254         
00255     Matrix<T>& operator=(const T& scalar)
00256     { 
00257         set(scalar); 
00258         return *this;
00259     }
00260 
00261 
00262     Subscript dim(Subscript d) const 
00263     {
00264 #ifdef TNT_BOUNDS_CHECK
00265         assert( d >= 1);
00266         assert( d <= 2);
00267 #endif
00268         return (d==1) ? m_ : ((d==2) ? n_ : 0); 
00269     }
00270 
00271     Subscript num_rows() const { return m_; }
00272     Subscript num_cols() const { return n_; }
00273 
00274 
00275 
00276 
00277     inline T* operator[](Subscript i)
00278     {
00279 #ifdef TNT_BOUNDS_CHECK
00280         assert(0<=i);
00281         assert(i < m_) ;
00282 #endif
00283         return row_[i];
00284     }
00285 
00286     inline const T* operator[](Subscript i) const
00287     {
00288 #ifdef TNT_BOUNDS_CHECK
00289         assert(0<=i);
00290         assert(i < m_) ;
00291 #endif
00292         return row_[i];
00293     }
00294 
00295     inline reference operator()(Subscript i)
00296     { 
00297 #ifdef TNT_BOUNDS_CHECK
00298         assert(1<=i);
00299         assert(i <= mn_) ;
00300 #endif
00301         return vm1_[i]; 
00302     }
00303 
00304     inline const_reference operator()(Subscript i) const
00305     { 
00306 #ifdef TNT_BOUNDS_CHECK
00307         assert(1<=i);
00308         assert(i <= mn_) ;
00309 #endif
00310         return vm1_[i]; 
00311     }
00312 
00313 
00314 
00315     inline reference operator()(Subscript i, Subscript j)
00316     { 
00317 #ifdef TNT_BOUNDS_CHECK
00318         assert(1<=i);
00319         assert(i <= m_) ;
00320         assert(1<=j);
00321         assert(j <= n_);
00322 #endif
00323         return  rowm1_[i][j]; 
00324     }
00325 
00326 
00327     
00328     inline const_reference operator() (Subscript i, Subscript j) const
00329     {
00330 #ifdef TNT_BOUNDS_CHECK
00331         assert(1<=i);
00332         assert(i <= m_) ;
00333         assert(1<=j);
00334         assert(j <= n_);
00335 #endif
00336         return rowm1_[i][j]; 
00337     }
00338 
00339 
00340 
00341 
00342 };
00343 
00344 
00345 /* ***************************  I/O  ********************************/
00346 
00347 template <class T>
00348 std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
00349 {
00350     Subscript M=A.num_rows();
00351     Subscript N=A.num_cols();
00352 
00353     s << M << " " << N << "\n";
00354 
00355     for (Subscript i=0; i<M; i++)
00356     {
00357         for (Subscript j=0; j<N; j++)
00358         {
00359             s << A[i][j] << " ";
00360         }
00361         s << "\n";
00362     }
00363 
00364 
00365     return s;
00366 }
00367 
00368 template <class T>
00369 std::istream& operator>>(std::istream &s, Matrix<T> &A)
00370 {
00371 
00372     Subscript M, N;
00373 
00374     s >> M >> N;
00375 
00376     if ( !(M == A.num_rows() && N == A.num_cols() ))
00377     {
00378         A.newsize(M,N);
00379     }
00380 
00381 
00382     for (Subscript i=0; i<M; i++)
00383         for (Subscript j=0; j<N; j++)
00384         {
00385             s >>  A[i][j];
00386         }
00387 
00388 
00389     return s;
00390 }
00391 
00392 // *******************[ basic matrix algorithms ]***************************
00393 
00394 
00395 template <class T>
00396 Matrix<T> operator+(const Matrix<T> &A, 
00397     const Matrix<T> &B)
00398 {
00399     Subscript M = A.num_rows();
00400     Subscript N = A.num_cols();
00401 
00402     assert(M==B.num_rows());
00403     assert(N==B.num_cols());
00404 
00405     Matrix<T> tmp(M,N);
00406     Subscript i,j;
00407 
00408     for (i=0; i<M; i++)
00409         for (j=0; j<N; j++)
00410             tmp[i][j] = A[i][j] + B[i][j];
00411 
00412     return tmp;
00413 }
00414 
00415 template <class T>
00416 Matrix<T> operator-(const Matrix<T> &A, 
00417     const Matrix<T> &B)
00418 {
00419     Subscript M = A.num_rows();
00420     Subscript N = A.num_cols();
00421 
00422     assert(M==B.num_rows());
00423     assert(N==B.num_cols());
00424 
00425     Matrix<T> tmp(M,N);
00426     Subscript i,j;
00427 
00428     for (i=0; i<M; i++)
00429         for (j=0; j<N; j++)
00430             tmp[i][j] = A[i][j] - B[i][j];
00431 
00432     return tmp;
00433 }
00434 
00435 template <class T>
00436 Matrix<T> mult_element(const Matrix<T> &A, 
00437     const Matrix<T> &B)
00438 {
00439     Subscript M = A.num_rows();
00440     Subscript N = A.num_cols();
00441 
00442     assert(M==B.num_rows());
00443     assert(N==B.num_cols());
00444 
00445     Matrix<T> tmp(M,N);
00446     Subscript i,j;
00447 
00448     for (i=0; i<M; i++)
00449         for (j=0; j<N; j++)
00450             tmp[i][j] = A[i][j] * B[i][j];
00451 
00452     return tmp;
00453 }
00454 
00455 
00456 template <class T>
00457 Matrix<T> transpose(const Matrix<T> &A)
00458 {
00459     Subscript M = A.num_rows();
00460     Subscript N = A.num_cols();
00461 
00462     Matrix<T> S(N,M);
00463     Subscript i, j;
00464 
00465     for (i=0; i<M; i++)
00466         for (j=0; j<N; j++)
00467             S[j][i] = A[i][j];
00468 
00469     return S;
00470 }
00471 
00472 
00473     
00474 template <class T>
00475 inline Matrix<T> matmult(const Matrix<T>  &A, 
00476     const Matrix<T> &B)
00477 {
00478 
00479 #ifdef TNT_BOUNDS_CHECK
00480     assert(A.num_cols() == B.num_rows());
00481 #endif
00482 
00483     Subscript M = A.num_rows();
00484     Subscript N = A.num_cols();
00485     Subscript K = B.num_cols();
00486 
00487     Matrix<T> tmp(M,K);
00488     T sum;
00489 
00490     for (Subscript i=0; i<M; i++)
00491     for (Subscript k=0; k<K; k++)
00492     {
00493         sum = 0;
00494         for (Subscript j=0; j<N; j++)
00495             sum = sum +  A[i][j] * B[j][k];
00496 
00497         tmp[i][k] = sum; 
00498     }
00499 
00500     return tmp;
00501 }
00502 
00503 template <class T>
00504 inline Matrix<T> operator*(const Matrix<T>  &A, 
00505     const Matrix<T> &B)
00506 {
00507     return matmult(A,B);
00508 }
00509 
00510 template <class T>
00511 inline int matmult(Matrix<T>& C, const Matrix<T>  &A, 
00512     const Matrix<T> &B)
00513 {
00514 
00515     assert(A.num_cols() == B.num_rows());
00516 
00517     Subscript M = A.num_rows();
00518     Subscript N = A.num_cols();
00519     Subscript K = B.num_cols();
00520 
00521     C.newsize(M,K);
00522 
00523     T sum;
00524 
00525     const T* row_i;
00526     const T* col_k;
00527 
00528     for (Subscript i=0; i<M; i++)
00529     for (Subscript k=0; k<K; k++)
00530     {
00531         row_i  = &(A[i][0]);
00532         col_k  = &(B[0][k]);
00533         sum = 0;
00534         for (Subscript j=0; j<N; j++)
00535         {
00536             sum  += *row_i * *col_k;
00537             row_i++;
00538             col_k += K;
00539         }
00540         C[i][k] = sum; 
00541     }
00542 
00543     return 0;
00544 }
00545 
00546 
00547 template <class T>
00548 Vector<T> matmult(const Matrix<T>  &A, const Vector<T> &x)
00549 {
00550 
00551 #ifdef TNT_BOUNDS_CHECK
00552     assert(A.num_cols() == x.dim());
00553 #endif
00554 
00555     Subscript M = A.num_rows();
00556     Subscript N = A.num_cols();
00557 
00558     Vector<T> tmp(M);
00559     T sum;
00560 
00561     for (Subscript i=0; i<M; i++)
00562     {
00563         sum = 0;
00564         const T* rowi = A[i];
00565         for (Subscript j=0; j<N; j++)
00566             sum = sum +  rowi[j] * x[j];
00567 
00568         tmp[i] = sum; 
00569     }
00570 
00571     return tmp;
00572 }
00573 
00574 template <class T>
00575 inline Vector<T> operator*(const Matrix<T>  &A, const Vector<T> &x)
00576 {
00577     return matmult(A,x);
00578 }
00579 
00580 } // namespace TNT
00581 
00582 #endif
00583 // CMAT_H