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