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