Blender V2.61 - r43446

fmat.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 // Fortran-compatible matrix: column oriented, 1-based (i,j) indexing
00031 
00032 #ifndef FMAT_H
00033 #define FMAT_H
00034 
00035 #include "subscript.h"
00036 #include "vec.h"
00037 #include <cstdlib>
00038 #include <cassert>
00039 #include <iostream>
00040 #ifdef TNT_USE_REGIONS
00041 #include "region2d.h"
00042 #endif
00043 
00044 // simple 1-based, column oriented Matrix class
00045 
00046 namespace TNT
00047 {
00048 
00049 template <class T>
00050 class Fortran_Matrix 
00051 {
00052 
00053 
00054   public:
00055 
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     T* v_;                  // these are adjusted to simulate 1-offset
00068     Subscript m_;
00069     Subscript n_;
00070     T** col_;           // these are adjusted to simulate 1-offset
00071 
00072     // internal helper function to create the array
00073     // of row pointers
00074 
00075     void initialize(Subscript M, Subscript N)
00076     {
00077         // adjust col_[] pointers so that they are 1-offset:
00078         //   col_[j][i] is really col_[j-1][i-1];
00079         //
00080         // v_[] is the internal contiguous array, it is still 0-offset
00081         //
00082         v_ = new T[M*N];
00083         col_ = new T*[N];
00084 
00085         assert(v_  != NULL);
00086         assert(col_ != NULL);
00087 
00088 
00089         m_ = M;
00090         n_ = N;
00091         T* p = v_ - 1;              
00092         for (Subscript i=0; i<N; i++)
00093         {
00094             col_[i] = p;
00095             p += M ;
00096             
00097         }
00098         col_ --; 
00099     }
00100    
00101     void copy(const T*  v)
00102     {
00103         Subscript N = m_ * n_;
00104         Subscript i;
00105 
00106 #ifdef TNT_UNROLL_LOOPS
00107         Subscript Nmod4 = N & 3;
00108         Subscript N4 = N - Nmod4;
00109 
00110         for (i=0; i<N4; i+=4)
00111         {
00112             v_[i] = v[i];
00113             v_[i+1] = v[i+1];
00114             v_[i+2] = v[i+2];
00115             v_[i+3] = v[i+3];
00116         }
00117 
00118         for (i=N4; i< N; i++)
00119             v_[i] = v[i];
00120 #else
00121 
00122         for (i=0; i< N; i++)
00123             v_[i] = v[i];
00124 #endif      
00125     }
00126 
00127     void set(const T& val)
00128     {
00129         Subscript N = m_ * n_;
00130         Subscript i;
00131 
00132 #ifdef TNT_UNROLL_LOOPS
00133         Subscript Nmod4 = N & 3;
00134         Subscript N4 = N - Nmod4;
00135 
00136         for (i=0; i<N4; i+=4)
00137         {
00138             v_[i] = val;
00139             v_[i+1] = val;
00140             v_[i+2] = val;
00141             v_[i+3] = val; 
00142         }
00143 
00144         for (i=N4; i< N; i++)
00145             v_[i] = val;
00146 #else
00147 
00148         for (i=0; i< N; i++)
00149             v_[i] = val;
00150         
00151 #endif      
00152     }
00153     
00154 
00155 
00156     void destroy()
00157     {     
00158         /* do nothing, if no memory has been previously allocated */
00159         if (v_ == NULL) return ;
00160 
00161         /* if we are here, then matrix was previously allocated */
00162         delete [] (v_);     
00163         col_ ++;                // changed back to 0-offset
00164         delete [] (col_);
00165     }
00166 
00167 
00168   public:
00169 
00170     T* begin() { return v_; }
00171     const T* begin() const { return v_;}
00172 
00173     T* end() { return v_ + m_*n_; }
00174     const T* end() const { return v_ + m_*n_; }
00175 
00176 
00177     // constructors
00178 
00179     Fortran_Matrix() : v_(0), m_(0), n_(0), col_(0)  {};
00180     Fortran_Matrix(const Fortran_Matrix<T> &A)
00181     {
00182         initialize(A.m_, A.n_);
00183         copy(A.v_);
00184     }
00185 
00186     Fortran_Matrix(Subscript M, Subscript N, const T& value = T())
00187     {
00188         initialize(M,N);
00189         set(value);
00190     }
00191 
00192     Fortran_Matrix(Subscript M, Subscript N, const T* v)
00193     {
00194         initialize(M,N);
00195         copy(v);
00196     }
00197 
00198 
00199     // destructor
00200     ~Fortran_Matrix()
00201     {
00202         destroy();
00203     }
00204 
00205 
00206     // assignments
00207     //
00208     Fortran_Matrix<T>& operator=(const Fortran_Matrix<T> &A)
00209     {
00210         if (v_ == A.v_)
00211             return *this;
00212 
00213         if (m_ == A.m_  && n_ == A.n_)      // no need to re-alloc
00214             copy(A.v_);
00215 
00216         else
00217         {
00218             destroy();
00219             initialize(A.m_, A.n_);
00220             copy(A.v_);
00221         }
00222 
00223         return *this;
00224     }
00225         
00226     Fortran_Matrix<T>& operator=(const T& scalar)
00227     { 
00228         set(scalar); 
00229         return *this;
00230     }
00231 
00232 
00233     Subscript dim(Subscript d) const 
00234     {
00235 #ifdef TNT_BOUNDS_CHECK
00236        assert( d >= 1);
00237         assert( d <= 2);
00238 #endif
00239         return (d==1) ? m_ : ((d==2) ? n_ : 0); 
00240     }
00241 
00242     Subscript num_rows() const { return m_; }
00243     Subscript num_cols() const { return n_; }
00244 
00245     Fortran_Matrix<T>& newsize(Subscript M, Subscript N)
00246     {
00247         if (num_rows() == M && num_cols() == N)
00248             return *this;
00249 
00250         destroy();
00251         initialize(M,N);
00252 
00253         return *this;
00254     }
00255 
00256 
00257 
00258     // 1-based element access
00259     //
00260     inline reference operator()(Subscript i, Subscript j)
00261     { 
00262 #ifdef TNT_BOUNDS_CHECK
00263         assert(1<=i);
00264         assert(i <= m_) ;
00265         assert(1<=j);
00266         assert(j <= n_);
00267 #endif
00268         return col_[j][i]; 
00269     }
00270 
00271     inline const_reference operator() (Subscript i, Subscript j) const
00272     {
00273 #ifdef TNT_BOUNDS_CHECK
00274         assert(1<=i);
00275         assert(i <= m_) ;
00276         assert(1<=j);
00277         assert(j <= n_);
00278 #endif
00279         return col_[j][i]; 
00280     }
00281 
00282 
00283 #ifdef TNT_USE_REGIONS
00284 
00285     typedef Region2D<Fortran_Matrix<T> > Region;
00286     typedef const_Region2D< Fortran_Matrix<T> > const_Region;
00287 
00288     Region operator()(const Index1D &I, const Index1D &J)
00289     {
00290         return Region(*this, I,J);
00291     }
00292 
00293     const_Region operator()(const Index1D &I, const Index1D &J) const
00294     {
00295         return const_Region(*this, I,J);
00296     }
00297 
00298 #endif
00299 
00300 
00301 };
00302 
00303 
00304 /* ***************************  I/O  ********************************/
00305 
00306 template <class T>
00307 std::ostream& operator<<(std::ostream &s, const Fortran_Matrix<T> &A)
00308 {
00309     Subscript M=A.num_rows();
00310     Subscript N=A.num_cols();
00311 
00312     s << M << " " << N << "\n";
00313 
00314     for (Subscript i=1; i<=M; i++)
00315     {
00316         for (Subscript j=1; j<=N; j++)
00317         {
00318             s << A(i,j) << " ";
00319         }
00320         s << "\n";
00321     }
00322 
00323 
00324     return s;
00325 }
00326 
00327 template <class T>
00328 std::istream& operator>>(std::istream &s, Fortran_Matrix<T> &A)
00329 {
00330 
00331     Subscript M, N;
00332 
00333     s >> M >> N;
00334 
00335     if ( !(M == A.num_rows() && N == A.num_cols()))
00336     {
00337         A.newsize(M,N);
00338     }
00339 
00340 
00341     for (Subscript i=1; i<=M; i++)
00342         for (Subscript j=1; j<=N; j++)
00343         {
00344             s >>  A(i,j);
00345         }
00346 
00347 
00348     return s;
00349 }
00350 
00351 // *******************[ basic matrix algorithms ]***************************
00352 
00353 
00354 template <class T>
00355 Fortran_Matrix<T> operator+(const Fortran_Matrix<T> &A, 
00356     const Fortran_Matrix<T> &B)
00357 {
00358     Subscript M = A.num_rows();
00359     Subscript N = A.num_cols();
00360 
00361     assert(M==B.num_rows());
00362     assert(N==B.num_cols());
00363 
00364     Fortran_Matrix<T> tmp(M,N);
00365     Subscript i,j;
00366 
00367     for (i=1; i<=M; i++)
00368         for (j=1; j<=N; j++)
00369             tmp(i,j) = A(i,j) + B(i,j);
00370 
00371     return tmp;
00372 }
00373 
00374 template <class T>
00375 Fortran_Matrix<T> operator-(const Fortran_Matrix<T> &A, 
00376     const Fortran_Matrix<T> &B)
00377 {
00378     Subscript M = A.num_rows();
00379     Subscript N = A.num_cols();
00380 
00381     assert(M==B.num_rows());
00382     assert(N==B.num_cols());
00383 
00384     Fortran_Matrix<T> tmp(M,N);
00385     Subscript i,j;
00386 
00387     for (i=1; i<=M; i++)
00388         for (j=1; j<=N; j++)
00389             tmp(i,j) = A(i,j) - B(i,j);
00390 
00391     return tmp;
00392 }
00393 
00394 // element-wise multiplication  (use matmult() below for matrix
00395 // multiplication in the linear algebra sense.)
00396 //
00397 //
00398 template <class T>
00399 Fortran_Matrix<T> mult_element(const Fortran_Matrix<T> &A, 
00400     const Fortran_Matrix<T> &B)
00401 {
00402     Subscript M = A.num_rows();
00403     Subscript N = A.num_cols();
00404 
00405     assert(M==B.num_rows());
00406     assert(N==B.num_cols());
00407 
00408     Fortran_Matrix<T> tmp(M,N);
00409     Subscript i,j;
00410 
00411     for (i=1; i<=M; i++)
00412         for (j=1; j<=N; j++)
00413             tmp(i,j) = A(i,j) * B(i,j);
00414 
00415     return tmp;
00416 }
00417 
00418 
00419 template <class T>
00420 Fortran_Matrix<T> transpose(const Fortran_Matrix<T> &A)
00421 {
00422     Subscript M = A.num_rows();
00423     Subscript N = A.num_cols();
00424 
00425     Fortran_Matrix<T> S(N,M);
00426     Subscript i, j;
00427 
00428     for (i=1; i<=M; i++)
00429         for (j=1; j<=N; j++)
00430             S(j,i) = A(i,j);
00431 
00432     return S;
00433 }
00434 
00435 
00436     
00437 template <class T>
00438 inline Fortran_Matrix<T> matmult(const Fortran_Matrix<T>  &A, 
00439     const Fortran_Matrix<T> &B)
00440 {
00441 
00442 #ifdef TNT_BOUNDS_CHECK
00443     assert(A.num_cols() == B.num_rows());
00444 #endif
00445 
00446     Subscript M = A.num_rows();
00447     Subscript N = A.num_cols();
00448     Subscript K = B.num_cols();
00449 
00450     Fortran_Matrix<T> tmp(M,K);
00451     T sum;
00452 
00453     for (Subscript i=1; i<=M; i++)
00454     for (Subscript k=1; k<=K; k++)
00455     {
00456         sum = 0;
00457         for (Subscript j=1; j<=N; j++)
00458             sum = sum +  A(i,j) * B(j,k);
00459 
00460         tmp(i,k) = sum; 
00461     }
00462 
00463     return tmp;
00464 }
00465 
00466 template <class T>
00467 inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A, 
00468     const Fortran_Matrix<T> &B)
00469 {
00470     return matmult(A,B);
00471 }
00472 
00473 template <class T>
00474 inline int matmult(Fortran_Matrix<T>& C, const Fortran_Matrix<T>  &A, 
00475     const Fortran_Matrix<T> &B)
00476 {
00477 
00478     assert(A.num_cols() == B.num_rows());
00479 
00480     Subscript M = A.num_rows();
00481     Subscript N = A.num_cols();
00482     Subscript K = B.num_cols();
00483 
00484     C.newsize(M,K);         // adjust shape of C, if necessary
00485 
00486 
00487     T sum; 
00488 
00489     const T* row_i;
00490     const T* col_k;
00491 
00492     for (Subscript i=1; i<=M; i++)
00493     {
00494         for (Subscript k=1; k<=K; k++)
00495         {
00496             row_i = &A(i,1);
00497             col_k = &B(1,k);
00498             sum = 0;
00499             for (Subscript j=1; j<=N; j++)
00500             {
00501                 sum +=  *row_i * *col_k;
00502                 row_i += M;
00503                 col_k ++;
00504             }
00505         
00506             C(i,k) = sum; 
00507         }
00508 
00509     }
00510 
00511     return 0;
00512 }
00513 
00514 
00515 template <class T>
00516 Vector<T> matmult(const Fortran_Matrix<T>  &A, const Vector<T> &x)
00517 {
00518 
00519 #ifdef TNT_BOUNDS_CHECK
00520     assert(A.num_cols() == x.dim());
00521 #endif
00522 
00523     Subscript M = A.num_rows();
00524     Subscript N = A.num_cols();
00525 
00526     Vector<T> tmp(M);
00527     T sum;
00528 
00529     for (Subscript i=1; i<=M; i++)
00530     {
00531         sum = 0;
00532         for (Subscript j=1; j<=N; j++)
00533             sum = sum +  A(i,j) * x(j);
00534 
00535         tmp(i) = sum; 
00536     }
00537 
00538     return tmp;
00539 }
00540 
00541 template <class T>
00542 inline Vector<T> operator*(const Fortran_Matrix<T>  &A, const Vector<T> &x)
00543 {
00544     return matmult(A,x);
00545 }
00546 
00547 template <class T>
00548 inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T>  &A, const T &x)
00549 {
00550     Subscript M = A.num_rows();
00551     Subscript N = A.num_cols();
00552 
00553     Subscript MN = M*N; 
00554 
00555     Fortran_Matrix<T> res(M,N);
00556     const T* a = A.begin();
00557     T* t = res.begin();
00558     T* tend = res.end();
00559 
00560     for (t=res.begin(); t < tend; t++, a++)
00561         *t = *a * x;
00562 
00563     return res;
00564 } 
00565 
00566 }  // namespace TNT
00567 
00568 #endif // FMAT_H
00569