Blender V2.61 - r43446
|
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