fmat.h
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:11k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. // Template Numerical Toolkit (TNT) for Linear Algebra
  2. //
  3. // BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
  4. // Please see http://math.nist.gov/tnt for updates
  5. //
  6. // R. Pozo
  7. // Mathematical and Computational Sciences Division
  8. // National Institute of Standards and Technology
  9. // Fortran-compatible matrix: column oriented, 1-based (i,j) indexing
  10. #ifndef FMAT_H
  11. #define FMAT_H
  12. #include "subscrpt.h"
  13. #include "vec.h"
  14. #include <stdlib.h>
  15. #include <assert.h>
  16. #include <iostream.h>
  17. #include <strstream.h>
  18. #ifdef TNT_USE_REGIONS
  19. #include "region2d.h"
  20. #endif
  21. // simple 1-based, column oriented Matrix class
  22. template <class T>
  23. class Fortran_matrix 
  24. {
  25.   public:
  26.     typedef         T   value_type;
  27.     typedef         T   element_type;
  28.     typedef         T*  pointer;
  29.     typedef         T*  iterator;
  30.     typedef         T&  reference;
  31.     typedef const   T*  const_iterator;
  32.     typedef const   T&  const_reference;
  33.     Subscript lbound() const { return 1;}
  34.  
  35.   protected:
  36.     T* v_;                  // these are adjusted to simulate 1-offset
  37.     Subscript m_;
  38.     Subscript n_;
  39.     T** col_;           // these are adjusted to simulate 1-offset
  40.     // internal helper function to create the array
  41.     // of row pointers
  42.     void initialize(Subscript M, Subscript N)
  43.     {
  44.         // adjust col_[] pointers so that they are 1-offset:
  45.         //   col_[j][i] is really col_[j-1][i-1];
  46.         //
  47.         // v_[] is the internal contiguous array, it is still 0-offset
  48.         //
  49.         v_ = new T[M*N];
  50.         col_ = new T*[N];
  51.         assert(v_  != NULL);
  52.         assert(col_ != NULL);
  53.         m_ = M;
  54.         n_ = N;
  55.         T* p = v_ - 1;              
  56.         for (Subscript i=0; i<N; i++)
  57.         {
  58.             col_[i] = p;
  59.             p += M ;
  60.             
  61.         }
  62.         col_ --; 
  63.     }
  64.    
  65.     void copy(const T*  v)
  66.     {
  67.         Subscript N = m_ * n_;
  68.         Subscript i;
  69. #ifdef TNT_UNROLL_LOOPS
  70.         Subscript Nmod4 = N & 4;
  71.         Subscript N4 = N - Nmod4;
  72.         for (i=0; i<N4; i+=4)
  73.         {
  74.             v_[i] = v[i];
  75.             v_[i+1] = v[i+1];
  76.             v_[i+2] = v[i+2];
  77.             v_[i+3] = v[i+3];
  78.         }
  79.         for (i=N4; i< N; i++)
  80.             v_[i] = v[i];
  81. #else
  82.         for (i=0; i< N; i++)
  83.             v_[i] = v[i];
  84. #endif      
  85.     }
  86.     void set(const T& val)
  87.     {
  88.         Subscript N = m_ * n_;
  89.         Subscript i;
  90. #ifdef TNT_UNROLL_LOOPS
  91.         Subscript Nmod4 = N & 4;
  92.         Subscript N4 = N - Nmod4;
  93.         for (i=0; i<N4; i+=4)
  94.         {
  95.             v_[i] = val;
  96.             v_[i+1] = val;
  97.             v_[i+2] = val;
  98.             v_[i+3] = val; 
  99.         }
  100.         for (i=N4; i< N; i++)
  101.             v_[i] = val;
  102. #else
  103.         for (i=0; i< N; i++)
  104.             v_[i] = val;
  105.         
  106. #endif      
  107.     }
  108.     
  109.     void destroy()
  110.     {     
  111.         /* do nothing, if no memory has been previously allocated */
  112.         if (v_ == NULL) return ;
  113.         /* if we are here, then matrix was previously allocated */
  114.         delete [] (v_);     
  115.         col_ ++;                // changed back to 0-offset
  116.         delete [] (col_);
  117.     }
  118.   public:
  119.     T* begin() { return v_; }
  120.     const T* begin() const { return v_;}
  121.     T* end() { return v_ + m_*n_; }
  122.     const T* end() const { return v_ + m_*n_; }
  123.     // constructors
  124.     Fortran_matrix() : v_(0), m_(0), n_(0), col_(0)  {};
  125.     Fortran_matrix(const Fortran_matrix<T> &A)
  126.     {
  127.         initialize(A.m_, A.n_);
  128.         copy(A.v_);
  129.     }
  130.     Fortran_matrix(Subscript M, Subscript N, const T& value = T(0))
  131.     {
  132.         initialize(M,N);
  133.         set(value);
  134.     }
  135.     Fortran_matrix(Subscript M, Subscript N, const T* v)
  136.     {
  137.         initialize(M,N);
  138.         copy(v);
  139.     }
  140.     Fortran_matrix(Subscript M, Subscript N, char *s)
  141.     {
  142.         initialize(M,N);
  143.         istrstream ins(s);
  144.         Subscript i, j;
  145.         for (i=1; i<=M; i++)
  146.             for (j=1; j<=N; j++)
  147.                 ins >> (*this)(i,j);
  148.     }
  149.     // destructor
  150.     ~Fortran_matrix()
  151.     {
  152.         destroy();
  153.     }
  154.     // assignments
  155.     //
  156.     Fortran_matrix<T>& operator=(const Fortran_matrix<T> &A)
  157.     {
  158.         if (v_ == A.v_)
  159.             return *this;
  160.         if (m_ == A.m_  && n_ == A.n_)      // no need to re-alloc
  161.             copy(A.v_);
  162.         else
  163.         {
  164.             destroy();
  165.             initialize(A.m_, A.n_);
  166.             copy(A.v_);
  167.         }
  168.         return *this;
  169.     }
  170.         
  171.     Fortran_matrix<T>& operator=(const T& scalar)
  172.     { 
  173.         set(scalar); 
  174.         return *this;
  175.     }
  176.     Subscript dim(Subscript d) const 
  177.     {
  178. #ifdef TNT_BOUNDS_CHECK
  179.        assert( d >= 1);
  180.         assert( d <= 2);
  181. #endif
  182.         return (d==1) ? m_ : ((d==2) ? n_ : 0); 
  183.     }
  184.     Subscript num_rows() const { return m_; }
  185.     Subscript num_cols() const { return n_; }
  186.     Fortran_matrix<T>& newsize(Subscript M, Subscript N)
  187.     {
  188.         if (num_rows() == M && num_cols() == N)
  189.             return *this;
  190.         destroy();
  191.         initialize(M,N);
  192.         return *this;
  193.     }
  194.     // 1-based element access
  195.     //
  196.     inline reference operator()(Subscript i, Subscript j)
  197.     { 
  198. #ifdef TNT_BOUNDS_CHECK
  199.         assert(1<=i);
  200.         assert(i <= m_) ;
  201.         assert(1<=j);
  202.         assert(j <= n_);
  203. #endif
  204.         return col_[j][i]; 
  205.     }
  206.     inline const_reference operator() (Subscript i, Subscript j) const
  207.     {
  208. #ifdef TNT_BOUNDS_CHECK
  209.         assert(1<=i);
  210.         assert(i <= m_) ;
  211.         assert(1<=j);
  212.         assert(j <= n_);
  213. #endif
  214.         return col_[j][i]; 
  215.     }
  216.     friend istream& operator>>(istream &s, Fortran_matrix<T> &A);
  217. #ifdef TNT_USE_REGIONS
  218.     typedef Region2D<Fortran_matrix<T> > Region;
  219.     typedef const_Region2D<Fortran_matrix<T>,T > const_Region;
  220.     Region operator()(const Index1D &I, const Index1D &J)
  221.     {
  222.         return Region(*this, I,J);
  223.     }
  224.     const_Region operator()(const Index1D &I, const Index1D &J) const
  225.     {
  226.         return const_Region(*this, I,J);
  227.     }
  228. #endif
  229. };
  230. /* ***************************  I/O  ********************************/
  231. template <class T>
  232. ostream& operator<<(ostream &s, const Fortran_matrix<T> &A)
  233. {
  234.     Subscript M=A.num_rows();
  235.     Subscript N=A.num_cols();
  236.     s << M << " " << N << endl;
  237.     for (Subscript i=1; i<=M; i++)
  238.     {
  239.         for (Subscript j=1; j<=N; j++)
  240.         {
  241.             s << A(i,j) << " ";
  242.         }
  243.         s << endl;
  244.     }
  245.     return s;
  246. }
  247. template <class T>
  248. istream& operator>>(istream &s, Fortran_matrix<T> &A)
  249. {
  250.     Subscript M, N;
  251.     s >> M >> N;
  252.     if ( !(M == A.m_ && N == A.n_) )
  253.     {
  254.         A.destroy();
  255.         A.initialize(M,N);
  256.     }
  257.     for (Subscript i=1; i<=M; i++)
  258.         for (Subscript j=1; j<=N; j++)
  259.         {
  260.             s >>  A(i,j);
  261.         }
  262.     return s;
  263. }
  264. //*******************[ basic matrix algorithms ]***************************
  265. template <class T>
  266. Fortran_matrix<T> operator+(const Fortran_matrix<T> &A, 
  267.     const Fortran_matrix<T> &B)
  268. {
  269.     Subscript M = A.num_rows();
  270.     Subscript N = A.num_cols();
  271.     assert(M==B.num_rows());
  272.     assert(N==B.num_cols());
  273.     Fortran_matrix<T> tmp(M,N);
  274.     Subscript i,j;
  275.     for (i=1; i<=M; i++)
  276.         for (j=1; j<=N; j++)
  277.             tmp(i,j) = A(i,j) + B(i,j);
  278.     return tmp;
  279. }
  280. template <class T>
  281. Fortran_matrix<T> operator-(const Fortran_matrix<T> &A, 
  282.     const Fortran_matrix<T> &B)
  283. {
  284.     Subscript M = A.num_rows();
  285.     Subscript N = A.num_cols();
  286.     assert(M==B.num_rows());
  287.     assert(N==B.num_cols());
  288.     Fortran_matrix<T> tmp(M,N);
  289.     Subscript i,j;
  290.     for (i=1; i<=M; i++)
  291.         for (j=1; j<=N; j++)
  292.             tmp(i,j) = A(i,j) - B(i,j);
  293.     return tmp;
  294. }
  295. // element-wise multiplication  (use matmult() below for matrix
  296. // multiplication in the linear algebra sense.)
  297. //
  298. //
  299. template <class T>
  300. Fortran_matrix<T> mult_element(const Fortran_matrix<T> &A, 
  301.     const Fortran_matrix<T> &B)
  302. {
  303.     Subscript M = A.num_rows();
  304.     Subscript N = A.num_cols();
  305.     assert(M==B.num_rows());
  306.     assert(N==B.num_cols());
  307.     Fortran_matrix<T> tmp(M,N);
  308.     Subscript i,j;
  309.     for (i=1; i<=M; i++)
  310.         for (j=1; j<=N; j++)
  311.             tmp(i,j) = A(i,j) * B(i,j);
  312.     return tmp;
  313. }
  314. template <class T>
  315. Fortran_matrix<T> transpose(const Fortran_matrix<T> &A)
  316. {
  317.     Subscript M = A.num_rows();
  318.     Subscript N = A.num_cols();
  319.     Fortran_matrix<T> S(N,M);
  320.     Subscript i, j;
  321.     for (i=1; i<=M; i++)
  322.         for (j=1; j<=N; j++)
  323.             S(j,i) = A(i,j);
  324.     return S;
  325. }
  326.     
  327. template <class T>
  328. inline Fortran_matrix<T> matmult(const Fortran_matrix<T>  &A, 
  329.     const Fortran_matrix<T> &B)
  330. {
  331. #ifdef TNT_BOUNDS_CHECK
  332.     assert(A.num_cols() == B.num_rows());
  333. #endif
  334.     Subscript M = A.num_rows();
  335.     Subscript N = A.num_cols();
  336.     Subscript K = B.num_cols();
  337.     Fortran_matrix<T> tmp(M,K);
  338.     T sum;
  339.     for (Subscript i=1; i<=M; i++)
  340.     for (Subscript k=1; k<=K; k++)
  341.     {
  342.         sum = 0;
  343.         for (Subscript j=1; j<=N; j++)
  344.             sum = sum +  A(i,j) * B(j,k);
  345.         tmp(i,k) = sum; 
  346.     }
  347.     return tmp;
  348. }
  349. template <class T>
  350. inline Fortran_matrix<T> operator*(const Fortran_matrix<T> &A, 
  351.     const Fortran_matrix<T> &B)
  352. {
  353.     return matmult(A,B);
  354. }
  355. template <class T>
  356. inline int matmult(Fortran_matrix<T>& C, const Fortran_matrix<T>  &A, 
  357.     const Fortran_matrix<T> &B)
  358. {
  359.     assert(A.num_cols() == B.num_rows());
  360.     Subscript M = A.num_rows();
  361.     Subscript N = A.num_cols();
  362.     Subscript K = B.num_cols();
  363.     C.newsize(M,K);         // adjust shape of C, if necessary
  364.     T sum; 
  365.     const T* row_i;
  366.     const T* col_k;
  367.     for (Subscript i=1; i<=M; i++)
  368.     {
  369.         for (Subscript k=1; k<=K; k++)
  370.         {
  371.             row_i = &A(i,1);
  372.             col_k = &B(1,k);
  373.             sum = 0;
  374.             for (Subscript j=1; j<=N; j++)
  375.             {
  376.                 sum +=  *row_i * *col_k;
  377.                 row_i += M;
  378.                 col_k ++;
  379.             }
  380.         
  381.             C(i,k) = sum; 
  382.         }
  383.     }
  384.     return 0;
  385. }
  386. template <class T>
  387. Vector<T> matmult(const Fortran_matrix<T>  &A, const Vector<T> &x)
  388. {
  389. #ifdef TNT_BOUNDS_CHECK
  390.     assert(A.num_cols() == x.dim());
  391. #endif
  392.     Subscript M = A.num_rows();
  393.     Subscript N = A.num_cols();
  394.     Vector<T> tmp(M);
  395.     T sum;
  396.     for (Subscript i=1; i<=M; i++)
  397.     {
  398.         sum = 0;
  399.         for (Subscript j=1; j<=N; j++)
  400.             sum = sum +  A(i,j) * x(j);
  401.         tmp(i) = sum; 
  402.     }
  403.     return tmp;
  404. }
  405. template <class T>
  406. inline Vector<T> operator*(const Fortran_matrix<T>  &A, const Vector<T> &x)
  407. {
  408.     return matmult(A,x);
  409. }
  410. template <class T>
  411. inline Fortran_matrix<T> operator*(const Fortran_matrix<T>  &A, const T &x)
  412. {
  413.     Subscript M = A.num_rows();
  414.     Subscript N = A.num_cols();
  415.     Subscript MN = M*N; 
  416.     Fortran_matrix<T> res(M,N);
  417.     const T* a = A.begin();
  418.     T* t = res.begin();
  419.     T* tend = res.end();
  420.     for (t=res.begin(); t < tend; t++, a++)
  421.         *t = *a * x;
  422.     return res;
  423. #endif
  424. // FMAT_H