Blender V2.61 - r43446

cmat.h

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