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 // 2D Regions for arrays and matrices 00030 00031 #ifndef REGION2D_H 00032 #define REGION2D_H 00033 00034 #include "index.h" 00035 #include <iostream> 00036 #include <cassert> 00037 00038 namespace TNT 00039 { 00040 00041 template <class Array2D> 00042 class const_Region2D; 00043 00044 00045 template <class Array2D> 00046 class Region2D 00047 { 00048 protected: 00049 00050 Array2D & A_; 00051 Subscript offset_[2]; // 0-offset internally 00052 Subscript dim_[2]; 00053 00054 public: 00055 typedef typename Array2D::value_type T; 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 Array2D & array() { return A_; } 00066 const Array2D & array() const { return A_; } 00067 Subscript lbound() const { return A_.lbound(); } 00068 Subscript num_rows() const { return dim_[0]; } 00069 Subscript num_cols() const { return dim_[1]; } 00070 Subscript offset(Subscript i) const // 1-offset 00071 { 00072 #ifdef TNT_BOUNDS_CHECK 00073 assert( A_.lbound() <= i); 00074 assert( i<= dim_[0] + A_.lbound()-1); 00075 #endif 00076 return offset_[i-A_.lbound()]; 00077 } 00078 00079 Subscript dim(Subscript i) const 00080 { 00081 #ifdef TNT_BOUNDS_CHECK 00082 assert( A_.lbound() <= i); 00083 assert( i<= dim_[0] + A_.lbound()-1); 00084 #endif 00085 return dim_[i-A_.lbound()]; 00086 } 00087 00088 00089 00090 Region2D(Array2D &A, Subscript i1, Subscript i2, Subscript j1, 00091 Subscript j2) : A_(A) 00092 { 00093 #ifdef TNT_BOUNDS_CHECK 00094 assert( i1 <= i2 ); 00095 assert( j1 <= j2); 00096 assert( A.lbound() <= i1); 00097 assert( i2<= A.dim(A.lbound()) + A.lbound()-1); 00098 assert( A.lbound() <= j1); 00099 assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 ); 00100 #endif 00101 00102 00103 offset_[0] = i1-A.lbound(); 00104 offset_[1] = j1-A.lbound(); 00105 dim_[0] = i2-i1+1; 00106 dim_[1] = j2-j1+1; 00107 } 00108 00109 Region2D(Array2D &A, const Index1D &I, const Index1D &J) : A_(A) 00110 { 00111 #ifdef TNT_BOUNDS_CHECK 00112 assert( I.lbound() <= I.ubound() ); 00113 assert( J.lbound() <= J.ubound() ); 00114 assert( A.lbound() <= I.lbound()); 00115 assert( I.ubound()<= A.dim(A.lbound()) + A.lbound()-1); 00116 assert( A.lbound() <= J.lbound()); 00117 assert( J.ubound() <= A.dim(A.lbound()+1) + A.lbound()-1 ); 00118 #endif 00119 00120 offset_[0] = I.lbound()-A.lbound(); 00121 offset_[1] = J.lbound()-A.lbound(); 00122 dim_[0] = I.ubound() - I.lbound() + 1; 00123 dim_[1] = J.ubound() - J.lbound() + 1; 00124 } 00125 00126 Region2D(Region2D<Array2D> &A, Subscript i1, Subscript i2, 00127 Subscript j1, Subscript j2) : A_(A.A_) 00128 { 00129 #ifdef TNT_BOUNDS_CHECK 00130 assert( i1 <= i2 ); 00131 assert( j1 <= j2); 00132 assert( A.lbound() <= i1); 00133 assert( i2<= A.dim(A.lbound()) + A.lbound()-1); 00134 assert( A.lbound() <= j1); 00135 assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 ); 00136 #endif 00137 offset_[0] = (i1 - A.lbound()) + A.offset_[0]; 00138 offset_[1] = (j1 - A.lbound()) + A.offset_[1]; 00139 dim_[0] = i2-i1 + 1; 00140 dim_[1] = j2-j1+1; 00141 } 00142 00143 Region2D<Array2D> operator()(Subscript i1, Subscript i2, 00144 Subscript j1, Subscript j2) 00145 { 00146 #ifdef TNT_BOUNDS_CHECK 00147 assert( i1 <= i2 ); 00148 assert( j1 <= j2); 00149 assert( A_.lbound() <= i1); 00150 assert( i2<= dim_[0] + A_.lbound()-1); 00151 assert( A_.lbound() <= j1); 00152 assert( j2<= dim_[1] + A_.lbound()-1 ); 00153 #endif 00154 return Region2D<Array2D>(A_, 00155 i1+offset_[0], offset_[0] + i2, 00156 j1+offset_[1], offset_[1] + j2); 00157 } 00158 00159 00160 Region2D<Array2D> operator()(const Index1D &I, 00161 const Index1D &J) 00162 { 00163 #ifdef TNT_BOUNDS_CHECK 00164 assert( I.lbound() <= I.ubound() ); 00165 assert( J.lbound() <= J.ubound() ); 00166 assert( A_.lbound() <= I.lbound()); 00167 assert( I.ubound()<= dim_[0] + A_.lbound()-1); 00168 assert( A_.lbound() <= J.lbound()); 00169 assert( J.ubound() <= dim_[1] + A_.lbound()-1 ); 00170 #endif 00171 00172 return Region2D<Array2D>(A_, I.lbound()+offset_[0], 00173 offset_[0] + I.ubound(), offset_[1]+J.lbound(), 00174 offset_[1] + J.ubound()); 00175 } 00176 00177 inline T & operator()(Subscript i, Subscript j) 00178 { 00179 #ifdef TNT_BOUNDS_CHECK 00180 assert( A_.lbound() <= i); 00181 assert( i<= dim_[0] + A_.lbound()-1); 00182 assert( A_.lbound() <= j); 00183 assert( j<= dim_[1] + A_.lbound()-1 ); 00184 #endif 00185 return A_(i+offset_[0], j+offset_[1]); 00186 } 00187 00188 inline const T & operator() (Subscript i, Subscript j) const 00189 { 00190 #ifdef TNT_BOUNDS_CHECK 00191 assert( A_.lbound() <= i); 00192 assert( i<= dim_[0] + A_.lbound()-1); 00193 assert( A_.lbound() <= j); 00194 assert( j<= dim_[1] + A_.lbound()-1 ); 00195 #endif 00196 return A_(i+offset_[0], j+offset_[1]); 00197 } 00198 00199 00200 Region2D<Array2D> & operator=(const Region2D<Array2D> &R) 00201 { 00202 Subscript M = num_rows(); 00203 Subscript N = num_cols(); 00204 00205 // make sure both sides conform 00206 assert(M == R.num_rows()); 00207 assert(N == R.num_cols()); 00208 00209 00210 Subscript start = R.lbound(); 00211 Subscript Mend = start + M - 1; 00212 Subscript Nend = start + N - 1; 00213 for (Subscript i=start; i<=Mend; i++) 00214 for (Subscript j=start; j<=Nend; j++) 00215 (*this)(i,j) = R(i,j); 00216 00217 return *this; 00218 } 00219 00220 Region2D<Array2D> & operator=(const const_Region2D<Array2D> &R) 00221 { 00222 Subscript M = num_rows(); 00223 Subscript N = num_cols(); 00224 00225 // make sure both sides conform 00226 assert(M == R.num_rows()); 00227 assert(N == R.num_cols()); 00228 00229 00230 Subscript start = R.lbound(); 00231 Subscript Mend = start + M - 1; 00232 Subscript Nend = start + N - 1; 00233 for (Subscript i=start; i<=Mend; i++) 00234 for (Subscript j=start; j<=Nend; j++) 00235 (*this)(i,j) = R(i,j); 00236 00237 return *this; 00238 } 00239 00240 Region2D<Array2D> & operator=(const Array2D &R) 00241 { 00242 Subscript M = num_rows(); 00243 Subscript N = num_cols(); 00244 00245 // make sure both sides conform 00246 assert(M == R.num_rows()); 00247 assert(N == R.num_cols()); 00248 00249 00250 Subscript start = R.lbound(); 00251 Subscript Mend = start + M - 1; 00252 Subscript Nend = start + N - 1; 00253 for (Subscript i=start; i<=Mend; i++) 00254 for (Subscript j=start; j<=Nend; j++) 00255 (*this)(i,j) = R(i,j); 00256 00257 return *this; 00258 } 00259 00260 Region2D<Array2D> & operator=(const T &scalar) 00261 { 00262 Subscript start = lbound(); 00263 Subscript Mend = lbound() + num_rows() - 1; 00264 Subscript Nend = lbound() + num_cols() - 1; 00265 00266 00267 for (Subscript i=start; i<=Mend; i++) 00268 for (Subscript j=start; j<=Nend; j++) 00269 (*this)(i,j) = scalar; 00270 00271 return *this; 00272 } 00273 00274 }; 00275 00276 //************************ 00277 00278 template <class Array2D> 00279 class const_Region2D 00280 { 00281 protected: 00282 00283 const Array2D & A_; 00284 Subscript offset_[2]; // 0-offset internally 00285 Subscript dim_[2]; 00286 00287 public: 00288 typedef typename Array2D::value_type T; 00289 typedef T value_type; 00290 typedef T element_type; 00291 typedef const T* const_iterator; 00292 typedef const T& const_reference; 00293 00294 const Array2D & array() const { return A_; } 00295 Subscript lbound() const { return A_.lbound(); } 00296 Subscript num_rows() const { return dim_[0]; } 00297 Subscript num_cols() const { return dim_[1]; } 00298 Subscript offset(Subscript i) const // 1-offset 00299 { 00300 #ifdef TNT_BOUNDS_CHECK 00301 assert( TNT_BASE_OFFSET <= i); 00302 assert( i<= dim_[0] + TNT_BASE_OFFSET-1); 00303 #endif 00304 return offset_[i-TNT_BASE_OFFSET]; 00305 } 00306 00307 Subscript dim(Subscript i) const 00308 { 00309 #ifdef TNT_BOUNDS_CHECK 00310 assert( TNT_BASE_OFFSET <= i); 00311 assert( i<= dim_[0] + TNT_BASE_OFFSET-1); 00312 #endif 00313 return dim_[i-TNT_BASE_OFFSET]; 00314 } 00315 00316 00317 const_Region2D(const Array2D &A, Subscript i1, Subscript i2, 00318 Subscript j1, Subscript j2) : A_(A) 00319 { 00320 #ifdef TNT_BOUNDS_CHECK 00321 assert( i1 <= i2 ); 00322 assert( j1 <= j2); 00323 assert( TNT_BASE_OFFSET <= i1); 00324 assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1); 00325 assert( TNT_BASE_OFFSET <= j1); 00326 assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 ); 00327 #endif 00328 00329 offset_[0] = i1-TNT_BASE_OFFSET; 00330 offset_[1] = j1-TNT_BASE_OFFSET; 00331 dim_[0] = i2-i1+1; 00332 dim_[1] = j2-j1+1; 00333 } 00334 00335 const_Region2D(const Array2D &A, const Index1D &I, const Index1D &J) 00336 : A_(A) 00337 { 00338 #ifdef TNT_BOUNDS_CHECK 00339 assert( I.lbound() <= I.ubound() ); 00340 assert( J.lbound() <= J.ubound() ); 00341 assert( TNT_BASE_OFFSET <= I.lbound()); 00342 assert( I.ubound()<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1); 00343 assert( TNT_BASE_OFFSET <= J.lbound()); 00344 assert( J.ubound() <= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 ); 00345 #endif 00346 00347 offset_[0] = I.lbound()-TNT_BASE_OFFSET; 00348 offset_[1] = J.lbound()-TNT_BASE_OFFSET; 00349 dim_[0] = I.ubound() - I.lbound() + 1; 00350 dim_[1] = J.ubound() - J.lbound() + 1; 00351 } 00352 00353 00354 const_Region2D(const_Region2D<Array2D> &A, Subscript i1, 00355 Subscript i2, 00356 Subscript j1, Subscript j2) : A_(A.A_) 00357 { 00358 #ifdef TNT_BOUNDS_CHECK 00359 assert( i1 <= i2 ); 00360 assert( j1 <= j2); 00361 assert( TNT_BASE_OFFSET <= i1); 00362 assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1); 00363 assert( TNT_BASE_OFFSET <= j1); 00364 assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 ); 00365 #endif 00366 offset_[0] = (i1 - TNT_BASE_OFFSET) + A.offset_[0]; 00367 offset_[1] = (j1 - TNT_BASE_OFFSET) + A.offset_[1]; 00368 dim_[0] = i2-i1 + 1; 00369 dim_[1] = j2-j1+1; 00370 } 00371 00372 const_Region2D<Array2D> operator()(Subscript i1, Subscript i2, 00373 Subscript j1, Subscript j2) 00374 { 00375 #ifdef TNT_BOUNDS_CHECK 00376 assert( i1 <= i2 ); 00377 assert( j1 <= j2); 00378 assert( TNT_BASE_OFFSET <= i1); 00379 assert( i2<= dim_[0] + TNT_BASE_OFFSET-1); 00380 assert( TNT_BASE_OFFSET <= j1); 00381 assert( j2<= dim_[0] + TNT_BASE_OFFSET-1 ); 00382 #endif 00383 return const_Region2D<Array2D>(A_, 00384 i1+offset_[0], offset_[0] + i2, 00385 j1+offset_[1], offset_[1] + j2); 00386 } 00387 00388 00389 const_Region2D<Array2D> operator()(const Index1D &I, 00390 const Index1D &J) 00391 { 00392 #ifdef TNT_BOUNDS_CHECK 00393 assert( I.lbound() <= I.ubound() ); 00394 assert( J.lbound() <= J.ubound() ); 00395 assert( TNT_BASE_OFFSET <= I.lbound()); 00396 assert( I.ubound()<= dim_[0] + TNT_BASE_OFFSET-1); 00397 assert( TNT_BASE_OFFSET <= J.lbound()); 00398 assert( J.ubound() <= dim_[1] + TNT_BASE_OFFSET-1 ); 00399 #endif 00400 00401 return const_Region2D<Array2D>(A_, I.lbound()+offset_[0], 00402 offset_[0] + I.ubound(), offset_[1]+J.lbound(), 00403 offset_[1] + J.ubound()); 00404 } 00405 00406 00407 inline const T & operator() (Subscript i, Subscript j) const 00408 { 00409 #ifdef TNT_BOUNDS_CHECK 00410 assert( TNT_BASE_OFFSET <= i); 00411 assert( i<= dim_[0] + TNT_BASE_OFFSET-1); 00412 assert( TNT_BASE_OFFSET <= j); 00413 assert( j<= dim_[1] + TNT_BASE_OFFSET-1 ); 00414 #endif 00415 return A_(i+offset_[0], j+offset_[1]); 00416 } 00417 00418 }; 00419 00420 00421 // ************** std::ostream algorithms ******************************* 00422 00423 template <class Array2D> 00424 std::ostream& operator<<(std::ostream &s, const const_Region2D<Array2D> &A) 00425 { 00426 Subscript start = A.lbound(); 00427 Subscript Mend=A.lbound()+ A.num_rows() - 1; 00428 Subscript Nend=A.lbound() + A.num_cols() - 1; 00429 00430 00431 s << A.num_rows() << " " << A.num_cols() << "\n"; 00432 for (Subscript i=start; i<=Mend; i++) 00433 { 00434 for (Subscript j=start; j<=Nend; j++) 00435 { 00436 s << A(i,j) << " "; 00437 } 00438 s << "\n"; 00439 } 00440 00441 00442 return s; 00443 } 00444 00445 template <class Array2D> 00446 std::ostream& operator<<(std::ostream &s, const Region2D<Array2D> &A) 00447 { 00448 Subscript start = A.lbound(); 00449 Subscript Mend=A.lbound()+ A.num_rows() - 1; 00450 Subscript Nend=A.lbound() + A.num_cols() - 1; 00451 00452 00453 s << A.num_rows() << " " << A.num_cols() << "\n"; 00454 for (Subscript i=start; i<=Mend; i++) 00455 { 00456 for (Subscript j=start; j<=Nend; j++) 00457 { 00458 s << A(i,j) << " "; 00459 } 00460 s << "\n"; 00461 } 00462 00463 00464 return s; 00465 00466 } 00467 00468 } // namespace TNT 00469 00470 #endif // REGION2D_H 00471