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