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