![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006-2012, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_OMATRIX_TLATE_H 00024 #define O2SCL_OMATRIX_TLATE_H 00025 00026 /** \file omatrix_tlate.h 00027 \brief File for definitions of matrices 00028 00029 \future The \c xmatrix class demonstrates how operator[] could 00030 return an ovector_array object and thus provide more 00031 bounds-checking. This would demand including a new parameter in 00032 omatrix_view_tlate which contains the vector type. 00033 */ 00034 00035 #include <iostream> 00036 #include <cstdlib> 00037 #include <string> 00038 #include <fstream> 00039 #include <sstream> 00040 00041 #include <gsl/gsl_matrix.h> 00042 #include <gsl/gsl_ieee_utils.h> 00043 00044 #include <o2scl/err_hnd.h> 00045 #include <o2scl/ovector_tlate.h> 00046 #include <o2scl/array.h> 00047 00048 #ifndef DOXYGENP 00049 namespace o2scl { 00050 #endif 00051 00052 /** \brief A const matrix view of omatrix objects 00053 */ 00054 template<class data_t, class mparent_t, class block_t> 00055 class omatrix_const_view_tlate : 00056 public mparent_t { 00057 00058 public: 00059 00060 /// \name Copy constructors 00061 //@{ 00062 /// Shallow copy constructor - create a new view of the same matrix 00063 omatrix_const_view_tlate(const omatrix_const_view_tlate &v) { 00064 mparent_t::block=0; 00065 mparent_t::data=v.data; 00066 mparent_t::size1=v.size1; 00067 mparent_t::size2=v.size2; 00068 mparent_t::tda=v.tda(); 00069 mparent_t::owner=0; 00070 } 00071 00072 /// Shallow copy constructor - create a new view of the same matrix 00073 omatrix_const_view_tlate& operator=(const omatrix_const_view_tlate &v) { 00074 mparent_t::block=0; 00075 mparent_t::data=v.data; 00076 mparent_t::size1=v.size1; 00077 mparent_t::size2=v.size2; 00078 mparent_t::tda=v.tda; 00079 mparent_t::owner=0; 00080 00081 return *this; 00082 } 00083 //@} 00084 00085 ~omatrix_const_view_tlate() {}; 00086 00087 /// \name Get and set methods 00088 //@{ 00089 /** \brief Array-like indexing 00090 */ 00091 const data_t *operator[](size_t i) const { 00092 #if O2SCL_NO_RANGE_CHECK 00093 #else 00094 if (i>=mparent_t::size1) { 00095 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00096 +" in omatrix_const_view_tlate::operator[] const. Size: "+ 00097 itos(mparent_t::size1)+ 00098 " (index should be less than size).").c_str(),gsl_eindex); 00099 return (mparent_t::data); 00100 } 00101 #endif 00102 return mparent_t::data+i*mparent_t::tda; 00103 } 00104 00105 /** \brief Array-like indexing 00106 */ 00107 const data_t &operator()(size_t i, size_t j) const { 00108 #if O2SCL_NO_RANGE_CHECK 00109 #else 00110 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00111 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00112 ", "+itos(j)+" out of bounds" 00113 +" in omatrix_cx_view_tlate::operator() const. Sizes: "+ 00114 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00115 " (indices should be less than sizes).").c_str(), 00116 gsl_eindex); 00117 return *(mparent_t::data); 00118 } 00119 #endif 00120 return *(mparent_t::data+i*mparent_t::tda+j); 00121 } 00122 00123 /** \brief Get (with optional range-checking) */ 00124 data_t get(size_t i, size_t j) const { 00125 #if O2SCL_NO_RANGE_CHECK 00126 #else 00127 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00128 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00129 ", "+itos(j)+" out of bounds" 00130 +" in omatrix_cx_view_tlate::get() const. Sizes: "+ 00131 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00132 " (indices should be less than sizes).").c_str(), 00133 gsl_eindex); 00134 return *(mparent_t::data); 00135 } 00136 #endif 00137 return *(mparent_t::data+i*mparent_t::tda+j); 00138 } 00139 00140 /** \brief Get pointer (with optional range-checking) */ 00141 data_t *get_ptr(size_t i, size_t j) { 00142 #if O2SCL_NO_RANGE_CHECK 00143 #else 00144 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00145 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00146 ", "+itos(j)+" out of bounds" 00147 +" in omatrix_cx_view_tlate::get_ptr(). Sizes: "+ 00148 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00149 " (indices should be less than sizes).").c_str(), 00150 gsl_eindex); 00151 return (mparent_t::data); 00152 } 00153 #endif 00154 return mparent_t::data+i*mparent_t::tda+j; 00155 } 00156 00157 /** \brief Get pointer (with optional range-checking) */ 00158 const data_t *get_const_ptr(size_t i, size_t j) const { 00159 #if O2SCL_NO_RANGE_CHECK 00160 #else 00161 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00162 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00163 ", "+itos(j)+" out of bounds" 00164 +" in omatrix_cx_view_tlate::get_const_ptr(). Sizes: "+ 00165 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00166 " (indices should be less than sizes).").c_str(), 00167 gsl_eindex); 00168 return (mparent_t::data); 00169 } 00170 #endif 00171 return (const data_t *)(mparent_t::data+i*mparent_t::tda+j); 00172 } 00173 00174 /** \brief Method to return number of rows 00175 00176 If no memory has been allocated, this will quietly 00177 return zero. 00178 */ 00179 size_t rows() const { 00180 return mparent_t::size1; 00181 } 00182 00183 /** \brief Method to return number of columns 00184 00185 If no memory has been allocated, this will quietly 00186 return zero. 00187 */ 00188 size_t cols() const { 00189 return mparent_t::size2; 00190 } 00191 00192 /** \brief Method to return matrix tda 00193 00194 If no memory has been allocated, this will quietly 00195 return zero. 00196 */ 00197 size_t tda() const { 00198 return mparent_t::tda; 00199 } 00200 //@} 00201 00202 /// \name Other methods 00203 //@{ 00204 /** \brief Return true if this object owns the data it refers to 00205 00206 This can be used to determine if an object is a "matrix_view", 00207 or a "matrix". If is_owner() is true, then it is an \ref 00208 omatrix_tlate object. 00209 */ 00210 bool is_owner() const { 00211 if (mparent_t::owner==1) return true; 00212 return false; 00213 } 00214 00215 /// The largest matrix element 00216 data_t max() const { 00217 data_t mx=*mparent_t::data; 00218 for(size_t i=0;i<mparent_t::size1;i++) { 00219 for(size_t j=0;j<mparent_t::size2;j++) { 00220 if (*(mparent_t::data+i*mparent_t::tda+j)>mx) { 00221 mx=*(mparent_t::data+i*mparent_t::tda+j); 00222 } 00223 } 00224 } 00225 return mx; 00226 } 00227 00228 /// The smallest matrix element 00229 data_t min() const { 00230 data_t mx=*mparent_t::data; 00231 for(size_t i=0;i<mparent_t::size1;i++) { 00232 for(size_t j=0;j<mparent_t::size2;j++) { 00233 if (*(mparent_t::data+i*mparent_t::tda+j)<mx) { 00234 mx=*(mparent_t::data+i*mparent_t::tda+j); 00235 } 00236 } 00237 } 00238 return mx; 00239 } 00240 00241 /** \brief Return a \c const gsl matrix */ 00242 const mparent_t *get_gsl_matrix_const() const { return this; }; 00243 //@} 00244 00245 #ifndef DOXYGEN_INTERNAL 00246 00247 protected: 00248 00249 /** \brief The default constructor 00250 */ 00251 omatrix_const_view_tlate() {}; 00252 00253 #endif 00254 00255 }; 00256 00257 /** \brief A base class for omatrix and omatrix_view 00258 */ 00259 template<class data_t, class mparent_t, class block_t> 00260 class omatrix_base_tlate : 00261 public omatrix_const_view_tlate<data_t,mparent_t,block_t> { 00262 00263 public: 00264 00265 /// \name Copy constructors 00266 //@{ 00267 /// Shallow copy constructor - create a new view of the same matrix 00268 omatrix_base_tlate(const omatrix_base_tlate &v) { 00269 mparent_t::block=0; 00270 mparent_t::data=v.data; 00271 mparent_t::size1=v.size1; 00272 mparent_t::size2=v.size2; 00273 mparent_t::tda=v.tda(); 00274 mparent_t::owner=0; 00275 } 00276 00277 /// Shallow copy constructor - create a new view of the same matrix 00278 omatrix_base_tlate& operator=(const omatrix_base_tlate &v) { 00279 mparent_t::block=0; 00280 mparent_t::data=v.data; 00281 mparent_t::size1=v.size1; 00282 mparent_t::size2=v.size2; 00283 mparent_t::tda=v.tda; 00284 mparent_t::owner=0; 00285 00286 return *this; 00287 } 00288 //@} 00289 00290 ~omatrix_base_tlate() {}; 00291 00292 /// \name Get and set methods 00293 //@{ 00294 /** \brief Array-like indexing 00295 */ 00296 data_t *operator[](size_t i) { 00297 #if O2SCL_NO_RANGE_CHECK 00298 #else 00299 if (i>=mparent_t::size1) { 00300 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00301 +" in omatrix_base_tlate::operator[]. Size: "+ 00302 itos(mparent_t::size1)+ 00303 " (index should be less than size).").c_str(),gsl_eindex); 00304 return (mparent_t::data); 00305 } 00306 #endif 00307 return mparent_t::data+i*mparent_t::tda; 00308 } 00309 00310 /** \brief Array-like indexing 00311 */ 00312 const data_t *operator[](size_t i) const { 00313 #if O2SCL_NO_RANGE_CHECK 00314 #else 00315 if (i>=mparent_t::size1) { 00316 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00317 +" in omatrix_base_tlate::operator[] const. Size: "+ 00318 itos(mparent_t::size1)+ 00319 " (index should be less than size).").c_str(),gsl_eindex); 00320 return (mparent_t::data); 00321 } 00322 #endif 00323 return mparent_t::data+i*mparent_t::tda; 00324 } 00325 00326 /** \brief Array-like indexing 00327 */ 00328 data_t &operator()(size_t i, size_t j) { 00329 #if O2SCL_NO_RANGE_CHECK 00330 #else 00331 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00332 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00333 ", "+itos(j)+" out of bounds" 00334 +" in omatrix_cx_view_tlate::operator(). Sizes: "+ 00335 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00336 " (indices should be less than sizes).").c_str(), 00337 gsl_eindex); 00338 return *(mparent_t::data); 00339 } 00340 #endif 00341 return *(mparent_t::data+i*mparent_t::tda+j); 00342 } 00343 00344 /** \brief Array-like indexing 00345 */ 00346 const data_t &operator()(size_t i, size_t j) const { 00347 #if O2SCL_NO_RANGE_CHECK 00348 #else 00349 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00350 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00351 ", "+itos(j)+" out of bounds" 00352 +" in omatrix_cx_view_tlate::operator() const. Sizes: "+ 00353 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00354 " (indices should be less than sizes).").c_str(), 00355 gsl_eindex); 00356 return *(mparent_t::data); 00357 } 00358 #endif 00359 return *(mparent_t::data+i*mparent_t::tda+j); 00360 } 00361 00362 /** \brief Get pointer (with optional range-checking) */ 00363 data_t *get_ptr(size_t i, size_t j) { 00364 #if O2SCL_NO_RANGE_CHECK 00365 #else 00366 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00367 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00368 ", "+itos(j)+" out of bounds" 00369 +" in omatrix_cx_view_tlate::get_ptr(). Sizes: "+ 00370 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00371 " (indices should be less than sizes).").c_str(), 00372 gsl_eindex); 00373 return (mparent_t::data); 00374 } 00375 #endif 00376 return mparent_t::data+i*mparent_t::tda+j; 00377 } 00378 00379 /** \brief Set (with optional range-checking) */ 00380 int set(size_t i, size_t j, data_t val) { 00381 #if O2SCL_NO_RANGE_CHECK 00382 #else 00383 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00384 O2SCL_ERR_RET((((std::string)"Array indices ")+itos(i)+ 00385 ", "+itos(j)+" out of bounds" 00386 +" in omatrix_cx_view_tlate::set(). Sizes: "+ 00387 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00388 " (indices should be less than sizes).").c_str(), 00389 gsl_eindex); 00390 } 00391 #endif 00392 *(mparent_t::data+i*mparent_t::tda+j)=val; 00393 return 0; 00394 } 00395 00396 /** \brief Set all of the value to be the value \c val */ 00397 int set_all(double val) { 00398 for(size_t i=0;i<mparent_t::size1;i++) { 00399 for(size_t j=0;j<mparent_t::size2;j++) { 00400 *(mparent_t::data+i*mparent_t::tda+j)=val; 00401 } 00402 } 00403 return 0; 00404 } 00405 //@} 00406 00407 /// \name Other methods 00408 //@{ 00409 /** \brief Return a gsl matrix */ 00410 mparent_t *get_gsl_matrix() { return this; }; 00411 //@} 00412 00413 /// \name Arithmetic 00414 //@{ 00415 /** \brief operator+= */ 00416 omatrix_base_tlate<data_t,mparent_t,block_t> &operator+= 00417 (const omatrix_base_tlate<data_t,mparent_t,block_t> &x) { 00418 size_t lsize=x.size1; 00419 if (lsize>mparent_t::size1) lsize=mparent_t::size1; 00420 size_t lsize2=x.size2; 00421 if (lsize2>mparent_t::size2) lsize2=mparent_t::size2; 00422 for(size_t i=0;i<lsize;i++) { 00423 for(size_t j=0;j<lsize2;j++) { 00424 (*this)[i][j]+=x[i][j]; 00425 } 00426 } 00427 00428 return *this; 00429 } 00430 00431 /** \brief operator-= */ 00432 omatrix_base_tlate<data_t,mparent_t,block_t> &operator-= 00433 (const omatrix_base_tlate<data_t,mparent_t,block_t> &x) { 00434 size_t lsize=x.size1; 00435 if (lsize>mparent_t::size1) lsize=mparent_t::size1; 00436 size_t lsize2=x.size2; 00437 if (lsize2>mparent_t::size2) lsize2=mparent_t::size2; 00438 for(size_t i=0;i<lsize;i++) { 00439 for(size_t j=0;j<lsize2;j++) { 00440 (*this)[i][j]+=x[i][j]; 00441 } 00442 } 00443 00444 return *this; 00445 } 00446 00447 /** \brief operator+= */ 00448 omatrix_base_tlate<data_t,mparent_t,block_t> 00449 &operator+=(const data_t &y) { 00450 for(size_t i=0;i<mparent_t::size1;i++) { 00451 for(size_t j=0;j<mparent_t::size2;j++) { 00452 (*this)[i][j]+=y; 00453 } 00454 } 00455 00456 return *this; 00457 } 00458 00459 /** \brief operator-= */ 00460 omatrix_base_tlate<data_t,mparent_t,block_t> 00461 &operator-=(const data_t &y) { 00462 for(size_t i=0;i<mparent_t::size1;i++) { 00463 for(size_t j=0;j<mparent_t::size2;j++) { 00464 (*this)[i][j]-=y; 00465 } 00466 } 00467 00468 return *this; 00469 } 00470 00471 /** \brief operator*= */ 00472 omatrix_base_tlate<data_t,mparent_t,block_t> 00473 &operator*=(const data_t &y) { 00474 for(size_t i=0;i<mparent_t::size1;i++) { 00475 for(size_t j=0;j<mparent_t::size2;j++) { 00476 (*this)[i][j]*=y; 00477 } 00478 } 00479 00480 return *this; 00481 } 00482 //@} 00483 00484 #ifndef DOXYGEN_INTERNAL 00485 00486 protected: 00487 00488 /** \brief The default constructor 00489 */ 00490 omatrix_base_tlate() {}; 00491 00492 #endif 00493 00494 }; 00495 00496 /** \brief A matrix view of double-precision numbers 00497 00498 This is a matrix view, which views a matrix stored somewhere 00499 else. For a full matrix template class with its own memory, see 00500 \ref omatrix_tlate . The basic matrix classes are built upon 00501 these templates. A matrix of double-precision numbers is an 00502 object of type \ref omatrix . See \ref vecmat_section in the 00503 User's Guide for more information. 00504 */ 00505 template<class data_t, class mparent_t, class block_t> 00506 class omatrix_view_tlate : 00507 public omatrix_base_tlate<data_t,mparent_t,block_t> { 00508 00509 public: 00510 00511 /// \name Copy constructors 00512 //@{ 00513 /// Shallow copy constructor - create a new view of the same matrix 00514 omatrix_view_tlate(const omatrix_view_tlate &v) : 00515 omatrix_base_tlate<data_t,mparent_t,block_t>() { 00516 mparent_t::block=0; 00517 mparent_t::data=v.data; 00518 mparent_t::size1=v.size1; 00519 mparent_t::size2=v.size2; 00520 mparent_t::tda=v.tda(); 00521 mparent_t::owner=0; 00522 } 00523 00524 /// Shallow copy constructor - create a new view of the same matrix 00525 omatrix_view_tlate& operator=(const omatrix_view_tlate &v) { 00526 mparent_t::block=0; 00527 mparent_t::data=v.data; 00528 mparent_t::size1=v.size1; 00529 mparent_t::size2=v.size2; 00530 mparent_t::tda=v.tda; 00531 mparent_t::owner=0; 00532 00533 return *this; 00534 } 00535 00536 /// Shallow copy constructor - create a new view of the same matrix 00537 omatrix_view_tlate(omatrix_base_tlate<data_t,mparent_t,block_t> &v) : 00538 omatrix_base_tlate<data_t,mparent_t,block_t>() { 00539 mparent_t::block=0; 00540 mparent_t::data=v.data; 00541 mparent_t::size1=v.size1; 00542 mparent_t::size2=v.size2; 00543 mparent_t::tda=v.tda(); 00544 mparent_t::owner=0; 00545 } 00546 00547 /// Shallow copy constructor - create a new view of the same matrix 00548 omatrix_view_tlate& operator= 00549 (omatrix_base_tlate<data_t,mparent_t,block_t> &v) { 00550 mparent_t::block=0; 00551 mparent_t::data=v.data; 00552 mparent_t::size1=v.size1; 00553 mparent_t::size2=v.size2; 00554 mparent_t::tda=v.tda; 00555 mparent_t::owner=0; 00556 00557 return *this; 00558 } 00559 //@} 00560 00561 ~omatrix_view_tlate() {}; 00562 00563 /// \name Get and set methods 00564 //@{ 00565 /** \brief Array-like indexing 00566 */ 00567 data_t *operator[](size_t i) const { 00568 #if O2SCL_NO_RANGE_CHECK 00569 #else 00570 if (i>=mparent_t::size1) { 00571 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 00572 +" in omatrix_view_tlate::operator[]. Size: "+ 00573 itos(mparent_t::size1)+ 00574 " (index should be less than size).").c_str(),gsl_eindex); 00575 return (mparent_t::data); 00576 } 00577 #endif 00578 return mparent_t::data+i*mparent_t::tda; 00579 } 00580 00581 /** \brief Array-like indexing 00582 */ 00583 data_t &operator()(size_t i, size_t j) const { 00584 #if O2SCL_NO_RANGE_CHECK 00585 #else 00586 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00587 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00588 ", "+itos(j)+" out of bounds" 00589 +" in omatrix_cx_view_tlate::operator(). Sizes: "+ 00590 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00591 " (indices should be less than sizes).").c_str(), 00592 gsl_eindex); 00593 return *(mparent_t::data); 00594 } 00595 #endif 00596 return *(mparent_t::data+i*mparent_t::tda+j); 00597 } 00598 00599 /** \brief Get pointer (with optional range-checking) */ 00600 data_t *get_ptr(size_t i, size_t j) const { 00601 #if O2SCL_NO_RANGE_CHECK 00602 #else 00603 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00604 O2SCL_ERR((((std::string)"Array indices ")+itos(i)+ 00605 ", "+itos(j)+" out of bounds" 00606 +" in omatrix_cx_view_tlate::get_ptr(). Sizes: "+ 00607 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00608 " (indices should be less than sizes).").c_str(), 00609 gsl_eindex); 00610 return (mparent_t::data); 00611 } 00612 #endif 00613 return mparent_t::data+i*mparent_t::tda+j; 00614 } 00615 00616 /** \brief Set (with optional range-checking) */ 00617 int set(size_t i, size_t j, data_t val) const { 00618 #if O2SCL_NO_RANGE_CHECK 00619 #else 00620 if (i>=mparent_t::size1 || j>=mparent_t::size2) { 00621 O2SCL_ERR_RET((((std::string)"Array indices ")+itos(i)+ 00622 ", "+itos(j)+" out of bounds" 00623 +" in omatrix_cx_view_tlate::set(). Sizes: "+ 00624 itos(mparent_t::size1)+","+itos(mparent_t::size2)+ 00625 " (indices should be less than sizes).").c_str(), 00626 gsl_eindex); 00627 } 00628 #endif 00629 *(mparent_t::data+i*mparent_t::tda+j)=val; 00630 return 0; 00631 } 00632 00633 /** \brief Set all of the value to be the value \c val */ 00634 int set_all(double val) const { 00635 for(size_t i=0;i<mparent_t::size1;i++) { 00636 for(size_t j=0;j<mparent_t::size2;j++) { 00637 *(mparent_t::data+i*mparent_t::tda+j)=val; 00638 } 00639 } 00640 return 0; 00641 } 00642 //@} 00643 00644 #ifndef DOXYGEN_INTERNAL 00645 00646 protected: 00647 00648 /** \brief The default constructor 00649 */ 00650 omatrix_view_tlate() {}; 00651 00652 #endif 00653 00654 }; 00655 00656 /** \brief A matrix of double-precision numbers 00657 00658 The basic matrix classes are built upon this template. A matrix 00659 of double-precision numbers is an object of type \ref omatrix , 00660 which is just a <tt>typedef</tt> defined using this class 00661 template. See \ref vecmat_section in the User's Guide for more 00662 information. 00663 */ 00664 template<class data_t, class mparent_t, class vparent_t, class block_t> 00665 class omatrix_tlate : 00666 public omatrix_base_tlate<data_t,mparent_t,block_t> { 00667 public: 00668 00669 /// \name Standard constructor 00670 //@{ 00671 /** \brief Create an omatrix of size \c n with owner as \c true. 00672 */ 00673 omatrix_tlate(size_t r=0, size_t c=0) { 00674 00675 mparent_t::block=0; 00676 mparent_t::data=0; 00677 mparent_t::size1=0; 00678 mparent_t::size2=0; 00679 mparent_t::tda=0; 00680 00681 // This must be set to 1 even if n=0 so that future 00682 // calls to operator= work properly 00683 mparent_t::owner=1; 00684 00685 if (r>0 && c>0) { 00686 mparent_t::block=(block_t *)malloc(sizeof(block_t)); 00687 if (mparent_t::block) { 00688 mparent_t::block->data=(data_t *)malloc(r*c*sizeof(data_t)); 00689 if (mparent_t::block->data) { 00690 mparent_t::block->size=r*c; 00691 mparent_t::data=mparent_t::block->data; 00692 mparent_t::size1=r; 00693 mparent_t::size2=c; 00694 mparent_t::tda=c; 00695 } else { 00696 std::free(mparent_t::block); 00697 O2SCL_ERR("No memory for data in omatrix_tlate constructor", 00698 gsl_enomem); 00699 } 00700 } else { 00701 O2SCL_ERR("No memory for block in omatrix_tlate contructor", 00702 gsl_enomem); 00703 } 00704 } 00705 } 00706 //@} 00707 00708 /// \name Copy constructors 00709 //@{ 00710 /// Deep copy constructor, allocate new space and make a copy 00711 omatrix_tlate(const omatrix_tlate &v) : 00712 omatrix_base_tlate<data_t,mparent_t,block_t>() { 00713 00714 mparent_t::block=0; 00715 mparent_t::data=0; 00716 mparent_t::size1=0; 00717 mparent_t::size2=0; 00718 mparent_t::tda=0; 00719 mparent_t::owner=1; 00720 00721 size_t n=v.size1; 00722 size_t n2=v.size2; 00723 if (n>0 && n2>0) { 00724 mparent_t::block=(block_t *)malloc(sizeof(block_t)); 00725 if (mparent_t::block) { 00726 mparent_t::block->data=(data_t *)malloc(n*n2*sizeof(data_t)); 00727 if (mparent_t::block->data) { 00728 mparent_t::block->size=n*n2; 00729 mparent_t::data=mparent_t::block->data; 00730 mparent_t::size1=n; 00731 mparent_t::size2=n2; 00732 mparent_t::tda=n2; 00733 mparent_t::owner=1; 00734 for(size_t i=0;i<n;i++) { 00735 for(size_t j=0;j<n2;j++) { 00736 *(mparent_t::data+i*mparent_t::tda+j)=v[i][j]; 00737 } 00738 } 00739 } else { 00740 std::free(mparent_t::block); 00741 O2SCL_ERR("No memory for data in omatrix_tlate constructor", 00742 gsl_enomem); 00743 } 00744 } else { 00745 O2SCL_ERR("No memory for block in omatrix_tlate contructor", 00746 gsl_enomem); 00747 } 00748 } else { 00749 mparent_t::size1=0; 00750 mparent_t::size2=0; 00751 mparent_t::tda=0; 00752 } 00753 } 00754 00755 /// Deep copy constructor, allocate new space and make a copy 00756 omatrix_tlate 00757 (const omatrix_const_view_tlate<data_t,mparent_t,block_t> &v) : 00758 omatrix_view_tlate<data_t,mparent_t,block_t>() { 00759 00760 mparent_t::block=0; 00761 mparent_t::data=0; 00762 mparent_t::size1=0; 00763 mparent_t::size2=0; 00764 mparent_t::tda=0; 00765 mparent_t::owner=1; 00766 00767 size_t r=v.rows(); 00768 size_t c=v.cols(); 00769 if (r>0 && c>0) { 00770 mparent_t::block=(block_t *)malloc(sizeof(block_t)); 00771 if (mparent_t::block) { 00772 mparent_t::block->data=(data_t *)malloc(r*c*sizeof(data_t)); 00773 if (mparent_t::block->data) { 00774 mparent_t::block->size=r*c; 00775 mparent_t::data=mparent_t::block->data; 00776 mparent_t::size1=v.size1; 00777 mparent_t::size2=v.size2; 00778 mparent_t::tda=v.tda; 00779 mparent_t::owner=1; 00780 for(size_t i=0;i<r;i++) { 00781 for(size_t j=0;i<c;j++) { 00782 *(mparent_t::data+i*mparent_t::tda+j)=v[i][j]; 00783 } 00784 } 00785 } else { 00786 std::free(mparent_t::block); 00787 O2SCL_ERR("No memory for data in omatrix_tlate constructor", 00788 gsl_enomem); 00789 } 00790 } else { 00791 O2SCL_ERR("No memory for block in omatrix_tlate contructor", 00792 gsl_enomem); 00793 } 00794 } else { 00795 mparent_t::size1=0; 00796 mparent_t::size2=0; 00797 mparent_t::tda=0; 00798 } 00799 } 00800 00801 /** \brief Deep copy constructor, if owner is true, allocate 00802 space and make a new copy, otherwise, just copy into the 00803 view 00804 */ 00805 omatrix_tlate& operator=(const omatrix_tlate &v) { 00806 00807 // Check for self-assignment 00808 if (this==&v) return *this; 00809 00810 mparent_t::block=0; 00811 mparent_t::data=0; 00812 mparent_t::size1=0; 00813 mparent_t::size2=0; 00814 mparent_t::tda=0; 00815 mparent_t::owner=1; 00816 00817 size_t sz=v.rows(); 00818 size_t sz2=v.cols(); 00819 mparent_t::data=0; 00820 if (mparent_t::owner) { 00821 allocate(mparent_t::size1,mparent_t::size2); 00822 } else { 00823 if (mparent_t::size1!=sz || mparent_t::size2!=sz2) { 00824 O2SCL_ERR("Sizes don't match in omatrix_tlate::operator=()", 00825 gsl_ebadlen); 00826 return *this; 00827 } 00828 } 00829 for(size_t i=0;i<sz;i++) { 00830 for(size_t j=0;j<sz2;j++) { 00831 *(mparent_t::data+i*mparent_t::tda+j)=v[i][j]; 00832 } 00833 } 00834 return *this; 00835 } 00836 00837 /** \brief Deep copy constructor, if owner is true, allocate 00838 space and make a new copy, otherwise, just copy into the 00839 view 00840 */ 00841 omatrix_tlate& operator= 00842 (const omatrix_const_view_tlate<data_t,mparent_t,block_t> &v) { 00843 00844 mparent_t::block=0; 00845 mparent_t::data=0; 00846 mparent_t::size1=0; 00847 mparent_t::size2=0; 00848 mparent_t::tda=0; 00849 mparent_t::owner=1; 00850 00851 // Check for self-assignment 00852 if (this==&v) return *this; 00853 00854 size_t r=v.rows(); 00855 size_t c=v.cols(); 00856 mparent_t::data=0; 00857 if (mparent_t::owner) { 00858 allocate(r,c); 00859 } else { 00860 if (mparent_t::size1!=r || mparent_t::size2!=c) { 00861 O2SCL_ERR("Sizes don't match in omatrix_tlate::operator=()", 00862 gsl_ebadlen); 00863 return *this; 00864 } 00865 } 00866 for(size_t i=0;i<r;i++) { 00867 for(size_t j=0;j<c;j++) { 00868 *(mparent_t::data+i*mparent_t::tda+j)=v[i][j]; 00869 } 00870 } 00871 return *this; 00872 } 00873 00874 /** \brief Deep copy from an array of ovectors 00875 */ 00876 omatrix_tlate(size_t n, 00877 ovector_base_tlate<data_t,vparent_t,block_t> ova[]) { 00878 if (n>0) { 00879 size_t n2=ova[0]; 00880 if (n2>0) { 00881 allocate(n,n2); 00882 for(size_t i=0;i<n;i++) { 00883 for(size_t j=0;j<n2;j++) { 00884 (*this)[i][j]=ova[i][j]; 00885 } 00886 } 00887 } 00888 } 00889 } 00890 00891 /** \brief Deep copy from an array of uvectors 00892 */ 00893 omatrix_tlate(size_t n, uvector_base_tlate<data_t> uva[]) { 00894 if (n>0) { 00895 size_t n2=uva[0]; 00896 if (n2>0) { 00897 allocate(n,n2); 00898 for(size_t i=0;i<n;i++) { 00899 for(size_t j=0;j<n2;j++) { 00900 (*this)[i][j]=uva[i][j]; 00901 } 00902 } 00903 } 00904 } 00905 } 00906 00907 /** \brief Deep copy from a C-style 2-d array 00908 */ 00909 omatrix_tlate(size_t n, size_t n2, data_t **csa) { 00910 if (n>0 && n2>0) { 00911 allocate(n,n2); 00912 for(size_t i=0;i<n;i++) { 00913 for(size_t j=0;j<n2;j++) { 00914 (*this)[i][j]=csa[i][j]; 00915 } 00916 } 00917 } 00918 } 00919 00920 //@} 00921 00922 ~omatrix_tlate() { 00923 if (mparent_t::size1>0) { 00924 if (mparent_t::owner==1) { 00925 if (mparent_t::block->size>0) { 00926 std::free(mparent_t::block->data); 00927 } 00928 std::free(mparent_t::block); 00929 mparent_t::size1=0; 00930 mparent_t::size2=0; 00931 } 00932 } 00933 } 00934 00935 /// \name Memory allocation 00936 //@{ 00937 /** \brief Allocate memory after freeing any memory 00938 presently in use 00939 */ 00940 int allocate(size_t nrows, size_t ncols) { 00941 if (mparent_t::size1>0 || mparent_t::size2>0) free(); 00942 00943 if (nrows>0 && ncols>0) { 00944 mparent_t::block=(block_t *)malloc(sizeof(block_t)); 00945 if (mparent_t::block) { 00946 mparent_t::block->data=(data_t *) 00947 malloc(nrows*ncols*sizeof(data_t)); 00948 if (mparent_t::block->data) { 00949 mparent_t::block->size=nrows*ncols; 00950 mparent_t::data=mparent_t::block->data; 00951 mparent_t::size1=nrows; 00952 mparent_t::size2=ncols; 00953 mparent_t::tda=ncols; 00954 mparent_t::owner=1; 00955 } else { 00956 std::free(mparent_t::block); 00957 O2SCL_ERR_RET("No memory for data in omatrix_tlate::allocate()", 00958 gsl_enomem); 00959 } 00960 } else { 00961 O2SCL_ERR_RET("No memory for block in omatrix_tlate::allocate()", 00962 gsl_enomem); 00963 } 00964 } else { 00965 O2SCL_ERR_RET("Zero size in omatrix::allocate()",gsl_einval); 00966 } 00967 return 0; 00968 } 00969 00970 /** \brief Free the memory 00971 00972 This function will safely do nothing if used without first 00973 allocating memory or if called multiple times in succession. 00974 */ 00975 int free() { 00976 if (mparent_t::size1>0) { 00977 if (mparent_t::owner==1) { 00978 if (mparent_t::block->size>0) { 00979 std::free(mparent_t::block->data); 00980 } 00981 std::free(mparent_t::block); 00982 } 00983 mparent_t::size1=0; 00984 mparent_t::size2=0; 00985 mparent_t::tda=0; 00986 } 00987 return 0; 00988 } 00989 //@} 00990 00991 /// \name Other methods 00992 //@{ 00993 /// \brief Compute the transpose (even if matrix is not square) 00994 omatrix_tlate<data_t,mparent_t,vparent_t,block_t> transpose() { 00995 omatrix_tlate<data_t,mparent_t,vparent_t,block_t> 00996 result(mparent_t::size2,mparent_t::size1); 00997 for(size_t i=0;i<mparent_t::size1;i++) { 00998 for(size_t j=0;j<mparent_t::size2;j++) { 00999 result[j][i]=(*this)[i][j]; 01000 } 01001 } 01002 } 01003 //@} 01004 01005 }; 01006 01007 #ifdef O2SCL_NEVER_DEFINED 01008 } 01009 { 01010 #endif 01011 01012 /** \brief Create a matrix from an array 01013 */ 01014 template<class data_t, class mparent_t, class block_t> 01015 class omatrix_array_tlate : 01016 public omatrix_view_tlate<data_t,mparent_t,block_t> { 01017 01018 public: 01019 01020 /** \brief Create a vector from \c dat with size \c n */ 01021 omatrix_array_tlate(data_t *dat, size_t ltda, 01022 size_t sz1, size_t sz2) { 01023 if (sz1==0 || sz2==0) { 01024 O2SCL_ERR("Failed to create omatrix from array, insufficient size.", 01025 gsl_einval); 01026 mparent_t::block=0; 01027 mparent_t::data=0; 01028 mparent_t::size1=0; 01029 mparent_t::size2=0; 01030 mparent_t::tda=0; 01031 mparent_t::owner=0; 01032 } 01033 mparent_t::block=0; 01034 mparent_t::data=dat; 01035 mparent_t::size1=sz1; 01036 mparent_t::size2=sz2; 01037 mparent_t::tda=ltda; 01038 mparent_t::owner=0; 01039 } 01040 }; 01041 01042 /** \brief Create a vector from a row of a matrix 01043 */ 01044 template<class data_t, class mparent_t, class vparent_t, class block_t> 01045 class omatrix_row_tlate : 01046 public ovector_view_tlate<data_t,vparent_t,block_t> { 01047 public: 01048 /** \brief Create a vector from row \c i of matrix \c m */ 01049 omatrix_row_tlate 01050 (omatrix_base_tlate<data_t,mparent_t,block_t> &m, 01051 size_t i) { 01052 if (i<m.size1) { 01053 vparent_t::size=m.size2; 01054 vparent_t::stride=1; 01055 vparent_t::data=m.data+m.tda()*i; 01056 vparent_t::owner=0; 01057 vparent_t::block=0; 01058 } else { 01059 O2SCL_ERR("Invalid row in omatrix_row_tlate constructor.", 01060 gsl_einval); 01061 vparent_t::size=0; 01062 vparent_t::stride=0; 01063 vparent_t::data=0; 01064 vparent_t::owner=0; 01065 vparent_t::block=0; 01066 } 01067 } 01068 }; 01069 01070 /** \brief Create a const vector from a row of a matrix 01071 */ 01072 template<class data_t, class mparent_t, class vparent_t, class block_t> 01073 class omatrix_const_row_tlate : 01074 public ovector_const_view_tlate<data_t,vparent_t,block_t> { 01075 public: 01076 /** \brief Create a vector from row \c i of matrix \c m */ 01077 omatrix_const_row_tlate 01078 (const omatrix_base_tlate<data_t,mparent_t,block_t> &m, 01079 size_t i) { 01080 if (i<m.size1) { 01081 vparent_t::size=m.size2; 01082 vparent_t::stride=1; 01083 vparent_t::data=m.data+m.tda*i; 01084 vparent_t::owner=0; 01085 vparent_t::block=0; 01086 } else { 01087 O2SCL_ERR("Invalid row in omatrix_const_row_tlate constructor.", 01088 gsl_einval); 01089 vparent_t::size=0; 01090 vparent_t::stride=0; 01091 vparent_t::data=0; 01092 vparent_t::owner=0; 01093 vparent_t::block=0; 01094 } 01095 } 01096 }; 01097 01098 /** \brief Create a vector from a column of a matrix 01099 01100 \future Also do a umatrix constructor since we 01101 can't do that with uvectors 01102 */ 01103 template<class data_t, class mparent_t, class vparent_t, class block_t> 01104 class omatrix_col_tlate : 01105 public ovector_view_tlate<data_t,vparent_t,block_t> { 01106 public: 01107 /** \brief Create a vector from col \c i of matrix \c m */ 01108 omatrix_col_tlate(omatrix_base_tlate<data_t,mparent_t,block_t> &m, 01109 size_t i) { 01110 if (i<m.size2) { 01111 vparent_t::size=m.size1; 01112 vparent_t::stride=m.tda(); 01113 vparent_t::data=m.data+i; 01114 vparent_t::owner=0; 01115 vparent_t::block=0; 01116 } else { 01117 O2SCL_ERR("Invalid column in omatrix_col_tlate constructor.", 01118 gsl_einval); 01119 vparent_t::size=0; 01120 vparent_t::stride=0; 01121 vparent_t::data=0; 01122 vparent_t::owner=0; 01123 vparent_t::block=0; 01124 } 01125 } 01126 }; 01127 01128 /** \brief Create a const vector from a column of a matrix 01129 */ 01130 template<class data_t, class mparent_t, class vparent_t, class block_t> 01131 class omatrix_const_col_tlate : 01132 public ovector_const_view_tlate<data_t,vparent_t,block_t> { 01133 public: 01134 /** \brief Create a vector from col \c i of matrix \c m */ 01135 omatrix_const_col_tlate 01136 (const omatrix_base_tlate<data_t,mparent_t,block_t> &m, size_t i) { 01137 if (i<m.size2) { 01138 vparent_t::size=m.size1; 01139 vparent_t::stride=m.tda(); 01140 vparent_t::data=m.data+i; 01141 vparent_t::owner=0; 01142 vparent_t::block=0; 01143 } else { 01144 O2SCL_ERR("Invalid column in omatrix_const_col_tlate constructor.", 01145 gsl_einval); 01146 vparent_t::size=0; 01147 vparent_t::stride=0; 01148 vparent_t::data=0; 01149 vparent_t::owner=0; 01150 vparent_t::block=0; 01151 } 01152 } 01153 }; 01154 01155 /** \brief Create a vector from the main diagonal 01156 */ 01157 template<class data_t, class mparent_t, class vparent_t, class block_t> 01158 class omatrix_diag_tlate : 01159 public ovector_view_tlate<data_t,vparent_t,block_t> { 01160 public: 01161 /** \brief Create a vector of the diagonal of matrix \c m */ 01162 omatrix_diag_tlate(omatrix_view_tlate<data_t,mparent_t,block_t> &m) { 01163 01164 if (m.size2<m.size1) vparent_t::size=m.size2; 01165 else vparent_t::size=m.size1; 01166 vparent_t::stride=m.tda()+1; 01167 vparent_t::data=m.data; 01168 vparent_t::owner=0; 01169 vparent_t::block=0; 01170 } 01171 }; 01172 01173 /** \brief Create a vector from the main diagonal 01174 */ 01175 template<class data_t, class mparent_t, class vparent_t, class block_t> 01176 class omatrix_const_diag_tlate : 01177 public ovector_const_view_tlate<data_t,vparent_t,block_t> { 01178 public: 01179 /** \brief Create a vector of the diagonal of matrix \c m */ 01180 omatrix_const_diag_tlate 01181 (const omatrix_view_tlate<data_t,mparent_t,block_t> &m) { 01182 01183 if (m.size2<m.size1) vparent_t::size=m.size2; 01184 else vparent_t::size=m.size1; 01185 vparent_t::stride=m.tda()+1; 01186 vparent_t::data=m.data; 01187 vparent_t::owner=0; 01188 vparent_t::block=0; 01189 } 01190 }; 01191 01192 01193 /// omatrix typedef 01194 typedef omatrix_tlate<double,gsl_matrix,gsl_vector_norm,gsl_block> omatrix; 01195 /// omatrix_view typedef 01196 typedef omatrix_view_tlate<double,gsl_matrix,gsl_block> omatrix_view; 01197 /// omatrix_const_view typedef 01198 typedef omatrix_const_view_tlate<double,gsl_matrix,gsl_block> 01199 omatrix_const_view; 01200 /// omatrix_base typedef 01201 typedef omatrix_base_tlate<double,gsl_matrix,gsl_block> omatrix_base; 01202 /// omatrix_row typedef 01203 typedef omatrix_row_tlate<double,gsl_matrix,gsl_vector_norm,gsl_block> 01204 omatrix_row; 01205 /// omatrix_col typedef 01206 typedef omatrix_col_tlate<double,gsl_matrix,gsl_vector_norm,gsl_block> 01207 omatrix_col; 01208 /// omatrix_const_row typedef 01209 typedef omatrix_const_row_tlate<double,gsl_matrix,gsl_vector_norm,gsl_block> 01210 omatrix_const_row; 01211 /// omatrix_const_col typedef 01212 typedef omatrix_const_col_tlate<double,gsl_matrix,gsl_vector_norm,gsl_block> 01213 omatrix_const_col; 01214 /// omatrix_diag typedef 01215 typedef omatrix_diag_tlate<double,gsl_matrix,gsl_vector_norm,gsl_block> 01216 omatrix_diag; 01217 /// omatrix_const_diag typedef 01218 typedef omatrix_const_diag_tlate<double,gsl_matrix,gsl_vector_norm, 01219 gsl_block> omatrix_const_diag; 01220 /// omatrix_array typedef 01221 typedef omatrix_array_tlate<double,gsl_matrix,gsl_block> 01222 omatrix_array; 01223 01224 /// omatrix_int typedef 01225 typedef omatrix_tlate<int,gsl_matrix_int,gsl_vector_int,gsl_block_int> 01226 omatrix_int; 01227 /// omatrix_int_view typedef 01228 typedef omatrix_view_tlate<int,gsl_matrix_int,gsl_block_int> 01229 omatrix_int_view; 01230 /// omatrix_int_base typedef 01231 typedef omatrix_base_tlate<int,gsl_matrix_int,gsl_block_int> 01232 omatrix_int_base; 01233 /// omatrix_int_const_view typedef 01234 typedef omatrix_const_view_tlate<int,gsl_matrix_int,gsl_block_int> 01235 omatrix_int_const_view; 01236 /// omatrix_int_row typedef 01237 typedef omatrix_row_tlate<int,gsl_matrix_int,gsl_vector_int, 01238 gsl_block_int> omatrix_int_row; 01239 /// omatrix_int_col typedef 01240 typedef omatrix_col_tlate<int,gsl_matrix_int,gsl_vector_int, 01241 gsl_block_int> omatrix_int_col; 01242 /// omatrix_int_const_row typedef 01243 typedef omatrix_const_row_tlate<int,gsl_matrix_int,gsl_vector_int, 01244 gsl_block_int> omatrix_int_const_row; 01245 /// omatrix_int_const_col typedef 01246 typedef omatrix_const_col_tlate<int,gsl_matrix_int,gsl_vector_int, 01247 gsl_block_int> omatrix_int_const_col; 01248 /// omatrix_int_diag typedef 01249 typedef omatrix_diag_tlate<int,gsl_matrix_int,gsl_vector_int, 01250 gsl_block_int> omatrix_int_diag; 01251 /// omatrix_int_const_diag typedef 01252 typedef omatrix_const_diag_tlate<int,gsl_matrix_int,gsl_vector_int, 01253 gsl_block_int> omatrix_int_const_diag; 01254 /// omatrix_int_array typedef 01255 typedef omatrix_array_tlate<int,gsl_matrix_int,gsl_block_int> 01256 omatrix_int_array; 01257 01258 /** \brief A operator for output of omatrix objects 01259 01260 This outputs all of the matrix elements. Each row is output with 01261 an endline character at the end of each row. Positive values are 01262 preceeded by an extra space. A 2x2 example: 01263 \verbatim 01264 -3.751935e-05 -6.785864e-04 01265 -6.785864e-04 1.631984e-02 01266 \endverbatim 01267 01268 The function \c gsl_ieee_double_to_rep() is used to determine 01269 the sign of a number, so that "-0.0" as distinct from "+0.0" 01270 is handled correctly. 01271 01272 \comment 01273 I had originally thought about removing this function, since 01274 it's superceded by matrix_out, but it's simpler to be able 01275 to just use the << operator so I keep it for now. 01276 \endcomment 01277 01278 \future This assumes that scientific mode is on and showpos 01279 is off. It'd be nice to fix this. 01280 01281 */ 01282 template<class data_t, class parent_t, class block_t> 01283 std::ostream &operator<< 01284 (std::ostream &os, 01285 const omatrix_const_view_tlate<data_t,parent_t,block_t> &v) { 01286 size_t i; 01287 gsl_ieee_double_rep r; 01288 for(i=0;i<v.rows()-1;i++) { 01289 for(size_t j=0;j<v.cols();j++) { 01290 gsl_ieee_double_to_rep(&(v[i][j]), &r); 01291 if (r.sign==1) os << v[i][j] << ' '; 01292 else os << ' ' << v[i][j] << ' '; 01293 } 01294 os << '\n'; 01295 } 01296 i=v.rows()-1; 01297 if (i>0) { 01298 for(size_t j=0;j<v.cols();j++) { 01299 gsl_ieee_double_to_rep(&(v[i][j]), &r); 01300 if (r.sign==1) os << v[i][j] << ' '; 01301 else os << ' ' << v[i][j] << ' '; 01302 } 01303 } 01304 return os; 01305 } 01306 01307 /** \brief A simple class to provide an \c allocate() function 01308 for \ref omatrix 01309 01310 */ 01311 class omatrix_alloc { 01312 public: 01313 /// Allocate \c v for \c i elements 01314 void allocate(omatrix &o, size_t i, size_t j) { o.allocate(i,j); } 01315 /// Free memory 01316 void free(omatrix &o, size_t i) { o.free(); } 01317 }; 01318 01319 #ifdef DOXGYENP2 01320 01321 /** \brief A matrix where the memory allocation is performed in 01322 the constructor 01323 */ 01324 template<size_t N, size_t M> class ofmatrix : public omatrix_tlate { 01325 01326 public: 01327 01328 /// Create a matrix 01329 ofmatrix(); 01330 }; 01331 01332 #else 01333 01334 template<size_t N, size_t M> class ofmatrix : 01335 public omatrix_tlate<double,gsl_matrix,gsl_vector,gsl_block> 01336 { 01337 public: 01338 ofmatrix() : omatrix_tlate<double,gsl_matrix,gsl_vector, 01339 gsl_block>(N,M) { 01340 } 01341 }; 01342 01343 #endif 01344 01345 /** \brief A version of \ref omatrix with better error checking 01346 01347 This demonstrates how operator[] could return an ovector_array 01348 object and thus provide more bounds-checking. This would demand 01349 including a new parameter in omatrix_view_tlate which contains 01350 the vector type. 01351 */ 01352 class xmatrix : public omatrix { 01353 public: 01354 xmatrix(size_t r=0, size_t c=0) : omatrix(r,c) { 01355 } 01356 01357 /** \brief Array-like indexing 01358 */ 01359 ovector_array operator[](size_t i) { 01360 #if O2SCL_NO_RANGE_CHECK 01361 #else 01362 if (i>=gsl_matrix::size1) { 01363 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 01364 +" in omatrix_view_tlate::operator[]. Size: "+ 01365 itos(gsl_matrix::size1)+ 01366 " (index should be less than size).").c_str(),gsl_eindex); 01367 } 01368 #endif 01369 return ovector_array(gsl_matrix::size2,gsl_matrix::data+ 01370 i*gsl_matrix::tda); 01371 } 01372 01373 /** \brief Array-like indexing 01374 */ 01375 const ovector_const_array operator[](size_t i) const { 01376 #if O2SCL_NO_RANGE_CHECK 01377 #else 01378 if (i>=gsl_matrix::size1) { 01379 O2SCL_ERR((((std::string)"Array index ")+itos(i)+" out of bounds" 01380 +" in omatrix_view_tlate::operator[]. Size: "+ 01381 itos(gsl_matrix::size1)+ 01382 " (index should be less than size).").c_str(),gsl_eindex); 01383 } 01384 #endif 01385 return ovector_const_array(gsl_matrix::size2,gsl_matrix::data+ 01386 i*gsl_matrix::tda); 01387 } 01388 }; 01389 01390 #ifndef DOXYGENP 01391 } 01392 #endif 01393 01394 #endif 01395
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).