00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 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_UMATRIX_TLATE_H 00024 #define O2SCL_UMATRIX_TLATE_H 00025 00026 /** \file umatrix_tlate.h 00027 \brief File for definitions of matrices 00028 */ 00029 00030 #include <iostream> 00031 #include <cstdlib> 00032 #include <string> 00033 #include <fstream> 00034 #include <sstream> 00035 00036 #include <gsl/gsl_matrix.h> 00037 #include <gsl/gsl_ieee_utils.h> 00038 00039 #include <o2scl/err_hnd.h> 00040 #include <o2scl/uvector_tlate.h> 00041 00042 #ifndef DOXYGENP 00043 namespace o2scl { 00044 #endif 00045 00046 //template<class data_t> class umatrix3d_view_tlate; 00047 //template<class data_t> class umatrix3d_tlate; 00048 00049 /** 00050 \brief A matrix view of double-precision numbers 00051 */ 00052 template<class data_t> class umatrix_view_tlate { 00053 00054 #ifndef DOXYGEN_INTERNAL 00055 00056 protected: 00057 00058 /// The data 00059 data_t *data; 00060 /// The number of rows 00061 size_t size1; 00062 /// The number of columns 00063 size_t size2; 00064 /// Zero if memory is owned elsewhere, 1 otherwise 00065 int owner; 00066 00067 //friend class umatrix3d_view_tlate<data_t>; 00068 //friend class umatrix3d_tlate<data_t>; 00069 00070 #endif 00071 00072 public: 00073 00074 /// \name Copy constructors 00075 //@{ 00076 /// So2scllow copy constructor - create a new view of the same matrix 00077 umatrix_view_tlate(const umatrix_view_tlate &v) { 00078 data=v.data; 00079 size1=v.size1; 00080 size2=v.size2; 00081 owner=0; 00082 } 00083 00084 /// So2scllow copy constructor - create a new view of the same matrix 00085 umatrix_view_tlate& operator=(const umatrix_view_tlate &v) { 00086 data=v.data; 00087 size1=v.size1; 00088 size2=v.size2; 00089 owner=0; 00090 00091 return *this; 00092 } 00093 //@} 00094 00095 ~umatrix_view_tlate() {}; 00096 00097 /// \name Get and set methods 00098 //@{ 00099 /** 00100 \brief Array-like indexing 00101 */ 00102 data_t *operator[](size_t i) { 00103 #if O2SCL_NO_RANGE_CHECK 00104 #else 00105 if (i>=size1) { 00106 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00107 +" in umatrix_view_tlate::operator[]. Size: "+ 00108 itos(size1)+ 00109 " (index should be less than size).").c_str(),gsl_index); 00110 return data; 00111 } 00112 #endif 00113 return data+i*size2; 00114 } 00115 00116 /** 00117 \brief Array-like indexing 00118 */ 00119 const data_t *operator[](size_t i) const { 00120 #if O2SCL_NO_RANGE_CHECK 00121 #else 00122 if (i>=size1) { 00123 set_err((((std::string)"Array index ")+itos(i)+" out of bounds" 00124 +" in umatrix_view_tlate::operator[] const. Size: "+ 00125 itos(size1)+ 00126 " (index should be less than size).").c_str(),gsl_index); 00127 return data; 00128 } 00129 #endif 00130 return data+i*size2; 00131 } 00132 00133 /** 00134 \brief Array-like indexing 00135 */ 00136 data_t &operator()(size_t i, size_t j) { 00137 #if O2SCL_NO_RANGE_CHECK 00138 #else 00139 if (i>=size1 || j>=size2) { 00140 set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+ 00141 ") out of bounds" 00142 +" in umatrix_view_tlate::operator(). Sizes: ("+ 00143 itos(size1)+","+itos(size2)+ 00144 ") (index should be less than size).").c_str(),gsl_index); 00145 return *data; 00146 } 00147 #endif 00148 return *(data+i*size2+j); 00149 } 00150 00151 /** 00152 \brief Array-like indexing 00153 */ 00154 const data_t &operator()(size_t i, size_t j) const { 00155 #if O2SCL_NO_RANGE_CHECK 00156 #else 00157 if (i>=size1 || j>=size2) { 00158 set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+ 00159 ") out of bounds" 00160 +" in umatrix_view_tlate::operator() const. Sizes: ("+ 00161 itos(size1)+","+itos(size2)+ 00162 ") (index should be less than size).").c_str(),gsl_index); 00163 return *data; 00164 } 00165 #endif 00166 return *(data+i*size2+j); 00167 } 00168 00169 /** \brief Get (with optional range-checking) */ 00170 data_t get(size_t i, size_t j) const { 00171 #if O2SCL_NO_RANGE_CHECK 00172 #else 00173 if (i>=size1 || j>=size2) { 00174 set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+ 00175 ") out of bounds" 00176 +" in umatrix_view_tlate::get(). Sizes: ("+ 00177 itos(size1)+","+itos(size2)+ 00178 ") (index should be less than size).").c_str(),gsl_index); 00179 return *data; 00180 } 00181 #endif 00182 return (data+i*size2+j); 00183 } 00184 00185 /** \brief Get pointer (with optional range-checking) */ 00186 data_t *get_ptr(size_t i, size_t j) { 00187 #if O2SCL_NO_RANGE_CHECK 00188 #else 00189 if (i>=size1 || j>=size2) { 00190 set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+ 00191 ") out of bounds" 00192 +" in umatrix_view_tlate::get_ptr(). Sizes: ("+ 00193 itos(size1)+","+itos(size2)+ 00194 ") (index should be less than size).").c_str(),gsl_index); 00195 return data; 00196 } 00197 #endif 00198 return data+i*size2+j; 00199 } 00200 00201 /** \brief Get pointer (with optional range-checking) */ 00202 const data_t *get_const_ptr(size_t i, size_t j) const { 00203 #if O2SCL_NO_RANGE_CHECK 00204 #else 00205 if (i>=size1 || j>=size2) { 00206 set_err((((std::string)"Indices (")+itos(i)+","+itos(j)+ 00207 ") out of bounds" 00208 +" in umatrix_view_tlate::get_const_ptr(). Sizes: ("+ 00209 itos(size1)+","+itos(size2)+ 00210 ") (index should be less than size).").c_str(),gsl_index); 00211 return (const data_t *)data; 00212 } 00213 #endif 00214 return (const data_t *)(data+i*size2+j); 00215 } 00216 00217 /** \brief Set (with optional range-checking) */ 00218 int set(size_t i, size_t j, data_t val) { 00219 #if O2SCL_NO_RANGE_CHECK 00220 #else 00221 if (i>=size1 || j>=size2) { 00222 set_err_ret((((std::string)"Indices (")+itos(i)+","+itos(j)+ 00223 ") out of bounds" 00224 +" in umatrix_view_tlate::set(). Sizes: ("+ 00225 itos(size1)+","+itos(size2)+ 00226 ") (index should be less than size).").c_str(),gsl_index); 00227 } 00228 #endif 00229 *(data+i*size2+j)=val; 00230 return 0; 00231 } 00232 00233 /** \brief Set all of the value to be the value \c val */ 00234 int set_all(double val) { 00235 for(size_t i=0;i<size1;i++) { 00236 for(size_t j=0;j<size2;j++) { 00237 *(data+i*size2+j)=val; 00238 } 00239 } 00240 return 0; 00241 } 00242 00243 /** 00244 \brief Method to return number of rows 00245 00246 If no memory has been allocated, this will quietly 00247 return zero. 00248 */ 00249 size_t rows() const { 00250 return size1; 00251 } 00252 00253 /** 00254 \brief Method to return number of columns 00255 00256 If no memory has been allocated, this will quietly 00257 return zero. 00258 */ 00259 size_t cols() const { 00260 return size2; 00261 } 00262 //@} 00263 00264 /// \name Other methods 00265 //@{ 00266 /// Return true if this object owns the data it refers to 00267 bool is_owner() const { 00268 if (owner==1) return true; 00269 return false; 00270 } 00271 //@} 00272 00273 /// \name Arithmetic 00274 //@{ 00275 /** \brief operator+= */ 00276 umatrix_view_tlate<data_t> &operator+= 00277 (const umatrix_view_tlate<data_t> &x) { 00278 size_t lsize=x.size1; 00279 if (lsize>size1) lsize=size1; 00280 size_t lsize2=x.size2; 00281 if (lsize2>size2) lsize2=size2; 00282 for(size_t i=0;i<lsize;i++) { 00283 for(size_t j=0;j<lsize2;j++) { 00284 (*this)[i][j]+=x[i][j]; 00285 } 00286 } 00287 00288 return *this; 00289 } 00290 00291 /** \brief operator-= */ 00292 umatrix_view_tlate<data_t> &operator-= 00293 (const umatrix_view_tlate<data_t> &x) { 00294 size_t lsize=x.size1; 00295 if (lsize>size1) lsize=size1; 00296 size_t lsize2=x.size2; 00297 if (lsize2>size2) lsize2=size2; 00298 for(size_t i=0;i<lsize;i++) { 00299 for(size_t j=0;j<lsize2;j++) { 00300 (*this)[i][j]+=x[i][j]; 00301 } 00302 } 00303 00304 return *this; 00305 } 00306 00307 /** \brief operator+= */ 00308 umatrix_view_tlate<data_t> &operator+=(const data_t &y) { 00309 for(size_t i=0;i<size1;i++) { 00310 for(size_t j=0;j<size2;j++) { 00311 (*this)[i][j]+=y; 00312 } 00313 } 00314 00315 return *this; 00316 } 00317 00318 /** \brief operator-= */ 00319 umatrix_view_tlate<data_t> &operator-=(const data_t &y) { 00320 for(size_t i=0;i<size1;i++) { 00321 for(size_t j=0;j<size2;j++) { 00322 (*this)[i][j]-=y; 00323 } 00324 } 00325 00326 return *this; 00327 } 00328 00329 /** \brief operator*= */ 00330 umatrix_view_tlate<data_t> &operator*=(const data_t &y) { 00331 for(size_t i=0;i<size1;i++) { 00332 for(size_t j=0;j<size2;j++) { 00333 (*this)[i][j]*=y; 00334 } 00335 } 00336 00337 return *this; 00338 } 00339 //@} 00340 00341 #ifndef DOXYGEN_INTERNAL 00342 00343 protected: 00344 00345 /** \brief Empty constructor provided for use by 00346 umatrix_tlate(const umatrix_tlate &v) 00347 */ 00348 umatrix_view_tlate() {}; 00349 00350 #endif 00351 00352 }; 00353 00354 /** 00355 \brief A matrix of double-precision numbers 00356 00357 */ 00358 template<class data_t> class umatrix_tlate : 00359 public umatrix_view_tlate<data_t> { 00360 public: 00361 00362 /// \name Standard constructor 00363 //@{ 00364 /** \brief Create an umatrix of size \c n with owner as 'true' 00365 */ 00366 umatrix_tlate(size_t r=0, size_t c=0) { 00367 00368 this->data=0; 00369 this->size1=0; 00370 this->size2=0; 00371 00372 // This must be set to 1 even if n=0 so that future 00373 // calls to operator= work properly 00374 this->owner=1; 00375 00376 if (r>0 && c>0) { 00377 this->data=(data_t *)malloc(r*c*sizeof(data_t)); 00378 if (this->data) { 00379 this->size1=r; 00380 this->size2=c; 00381 } else { 00382 set_err("No memory for data in umatrix_tlate constructor", 00383 gsl_enomem); 00384 } 00385 } 00386 } 00387 //@} 00388 00389 /// \name Copy constructors 00390 //@{ 00391 /// Deep copy constructor, allocate new space and make a copy 00392 umatrix_tlate(const umatrix_tlate &v) : 00393 umatrix_view_tlate<data_t>() { 00394 size_t n=v.size1; 00395 size_t n2=v.size2; 00396 if (n>0 && n2>0) { 00397 this->data=(data_t *)malloc(n*n2*sizeof(data_t)); 00398 if (this->data) { 00399 this->size1=n; 00400 this->size2=n2; 00401 this->owner=1; 00402 for(size_t i=0;i<n;i++) { 00403 for(size_t j=0;j<n2;j++) { 00404 *(this->data+i*this->size2+j)=v[i][j]; 00405 } 00406 } 00407 } else { 00408 set_err("No memory for data in umatrix_tlate constructor", 00409 gsl_enomem); 00410 } 00411 } else { 00412 this->size1=0; 00413 this->size2=0; 00414 } 00415 } 00416 00417 /// Deep copy constructor, allocate new space and make a copy 00418 umatrix_tlate 00419 (const umatrix_view_tlate<data_t> &v) : 00420 umatrix_view_tlate<data_t>() { 00421 size_t r=v.rows(); 00422 size_t c=v.cols(); 00423 if (r>0 && c>0) { 00424 this->data=(data_t *)malloc(r*c*sizeof(data_t)); 00425 if (this->data) { 00426 this->size1=v.size1; 00427 this->size2=v.size2; 00428 this->owner=1; 00429 for(size_t i=0;i<r;i++) { 00430 for(size_t j=0;i<c;j++) { 00431 *(this->data+i*this->size2+j)=v[i][j]; 00432 } 00433 } 00434 } else { 00435 set_err("No memory for data in umatrix_tlate constructor", 00436 gsl_enomem); 00437 } 00438 } else { 00439 this->size1=0; 00440 this->size2=0; 00441 } 00442 } 00443 00444 /** \brief Deep copy constructor, if owner is true, allocate space and 00445 make a new copy, otherwise, just copy into the view 00446 */ 00447 umatrix_tlate& operator=(const umatrix_tlate &v) { 00448 size_t sze=v.size1; 00449 size_t sze2=v.size2; 00450 if (this->owner) { 00451 allocate(sze,sze2); 00452 } else { 00453 if (this->size1!=sze || this->size2!=sze2) { 00454 set_err("Sizes don't match in umatrix_tlate::operator=()", 00455 gsl_ebadlen); 00456 return *this; 00457 } 00458 } 00459 for(size_t i=0;i<sze;i++) { 00460 for(size_t j=0;j<sze2;j++) { 00461 *(this->data+i*this->size2+j)=v[i][j]; 00462 } 00463 } 00464 return *this; 00465 } 00466 00467 /** \brief Deep copy constructor, if owner is true, allocate space and 00468 make a new copy, otherwise, just copy into the view 00469 */ 00470 umatrix_tlate& operator= 00471 (const umatrix_view_tlate<data_t> &v) { 00472 size_t sze=v.rows(); 00473 size_t sze2=v.cols(); 00474 if (this->owner) { 00475 allocate(sze,sze2); 00476 } else { 00477 if (this->size1!=sze || this->size2!=sze2) { 00478 set_err("Sizes don't match in umatrix_tlate::operator=()", 00479 gsl_ebadlen); 00480 return *this; 00481 } 00482 } 00483 for(size_t i=0;i<sze;i++) { 00484 for(size_t j=0;j<sze2;j++) { 00485 *(this->data+i*this->size2+j)=v[i][j]; 00486 } 00487 } 00488 return *this; 00489 } 00490 00491 /** \brief Deep copy from an array of uvectors 00492 */ 00493 umatrix_tlate(size_t n, uvector_view_tlate<data_t> uva[]) { 00494 if (n>0) { 00495 size_t n2=uva[0]; 00496 if (n2>0) { 00497 allocate(n,n2); 00498 for(size_t i=0;i<n;i++) { 00499 for(size_t j=0;j<n2;j++) { 00500 (*this)[i][j]=uva[i][j]; 00501 } 00502 } 00503 } 00504 } 00505 } 00506 00507 /** \brief Deep copy from a C-style 2-d array 00508 */ 00509 umatrix_tlate(size_t n, size_t n2, data_t **csa) { 00510 if (n>0 && n2>0) { 00511 allocate(n,n2); 00512 for(size_t i=0;i<n;i++) { 00513 for(size_t j=0;j<n2;j++) { 00514 (*this)[i][j]=csa[i][j]; 00515 } 00516 } 00517 } 00518 } 00519 00520 //@} 00521 00522 ~umatrix_tlate() { 00523 if (this->size1>0) { 00524 if (this->owner==1) { 00525 std::free(this->data); 00526 this->size1=0; 00527 this->size2=0; 00528 } 00529 } 00530 } 00531 00532 /// \name Memory allocation 00533 //@{ 00534 /** 00535 \brief Allocate memory after freeing any memory presently in use 00536 */ 00537 int allocate(size_t nrows, size_t ncols) { 00538 if (this->size1>0 || this->size2>0) free(); 00539 00540 if (nrows>0 && ncols>0) { 00541 this->data=(data_t *)malloc(nrows*ncols*sizeof(data_t)); 00542 if (this->data) { 00543 this->size1=nrows; 00544 this->size2=ncols; 00545 this->owner=1; 00546 } else { 00547 set_err_ret("No memory for data in umatrix_tlate::allocate()", 00548 gsl_enomem); 00549 } 00550 } else { 00551 set_err_ret("Zero size in umatrix::allocate()",gsl_einval); 00552 } 00553 return 0; 00554 } 00555 00556 /** 00557 \brief Free the memory 00558 00559 This function will safely do nothing if used without first 00560 allocating memory or if called multiple times in succession. 00561 */ 00562 int free() { 00563 if (this->size1>0) { 00564 if (this->owner==1) { 00565 std::free(this->data); 00566 } 00567 this->size1=0; 00568 this->size2=0; 00569 } 00570 return 0; 00571 } 00572 //@} 00573 00574 /// \name Other methods 00575 //@{ 00576 /// \brief Compute the transpose (even if matrix is not square) 00577 umatrix_tlate<data_t> transpose() { 00578 umatrix_tlate<data_t> result(this->size2,this->size1); 00579 for(size_t i=0;i<this->size1;i++) { 00580 for(size_t j=0;j<this->size2;j++) { 00581 result[j][i]=(*this)[i][j]; 00582 } 00583 } 00584 } 00585 //@} 00586 00587 }; 00588 00589 /** \brief Create a vector from a row of a matrix 00590 */ 00591 template<class data_t> class umatrix_row_tlate : 00592 public uvector_view_tlate<data_t> { 00593 public: 00594 /** \brief Create a vector from row \c i of matrix \c m */ 00595 umatrix_row_tlate(umatrix_view_tlate<data_t> &m, 00596 size_t i) { 00597 this->sz=0; 00598 this->data=0; 00599 this->owner=0; 00600 if (i<m.rows()) { 00601 this->sz=m.cols(); 00602 this->data=m[0]+m.cols()*i; 00603 } 00604 } 00605 }; 00606 00607 /** \brief Create a const vector from a row of a matrix 00608 */ 00609 template<class data_t> class umatrix_const_row_tlate : 00610 public uvector_view_tlate<data_t> { 00611 public: 00612 /** \brief Create a vector from row \c i of matrix \c m */ 00613 umatrix_const_row_tlate 00614 (const umatrix_view_tlate<data_t> &m, 00615 size_t i) { 00616 if (i<m.size1) { 00617 this->sz=m.cols(); 00618 this->data=m[0]+m.cols()*i; 00619 this->owner=0; 00620 } 00621 } 00622 }; 00623 00624 /// umatrix typedef 00625 typedef umatrix_tlate<double> umatrix; 00626 /// umatrix_view typedef 00627 typedef umatrix_view_tlate<double> umatrix_view; 00628 /// umatrix_row typedef 00629 typedef umatrix_row_tlate<double> umatrix_row; 00630 /// umatrix_const_row typedef 00631 typedef umatrix_const_row_tlate<double> umatrix_const_row; 00632 00633 /// umatrix_int typedef 00634 typedef umatrix_tlate<int> umatrix_int; 00635 /// umatrix_int_view typedef 00636 typedef umatrix_view_tlate<int> umatrix_int_view; 00637 /// umatrix_int_row typedef 00638 typedef umatrix_row_tlate<int> umatrix_int_row; 00639 /// umatrix_int_const_row typedef 00640 typedef umatrix_const_row_tlate<int> umatrix_int_const_row; 00641 00642 /** \brief A operator for naive matrix output 00643 00644 00645 This outputs all of the matrix elements. Each row is output with 00646 an endline character at the end of each row. Positive values are 00647 preceeded by an extra space. A 2x2 example: 00648 \verbatim 00649 -3.751935e-05 -6.785864e-04 00650 -6.785864e-04 1.631984e-02 00651 \endverbatim 00652 00653 The function \c gsl_ieee_double_to_rep() is used to determine 00654 the sign of a number, so that "-0.0" as distinct from "+0.0" 00655 is handled correctly. 00656 00657 \todo This assumes that scientific mode is on and showpos 00658 is off. It'd be nice to fix this. 00659 00660 */ 00661 template<class data_t> std::ostream &operator<< 00662 (std::ostream &os, const umatrix_view_tlate<data_t> &v) { 00663 size_t i; 00664 gsl_ieee_double_rep r; 00665 for(i=0;i<v.rows()-1;i++) { 00666 for(size_t j=0;j<v.cols();j++) { 00667 gsl_ieee_double_to_rep(&(v[i][j]), &r); 00668 if (r.sign==1) os << v[i][j] << ' '; 00669 else os << ' ' << v[i][j] << ' '; 00670 } 00671 os << '\n'; 00672 } 00673 i=v.rows()-1; 00674 if (i>0) { 00675 for(size_t j=0;j<v.cols();j++) { 00676 gsl_ieee_double_to_rep(&(v[i][j]), &r); 00677 if (r.sign==1) os << v[i][j] << ' '; 00678 else os << ' ' << v[i][j] << ' '; 00679 } 00680 } 00681 return os; 00682 } 00683 00684 /** \brief A simple class to provide an \c allocate() function 00685 for \ref umatrix 00686 00687 00688 */ 00689 class umatrix_alloc { 00690 public: 00691 /// Allocate \c v for \c i elements 00692 void allocate(umatrix &o, int i, int j) { o.allocate(i,j); } 00693 /// Free memory 00694 void free(umatrix &o) { o.free(); } 00695 }; 00696 00697 /** \brief A matrix where the memory allocation is performed in 00698 the constructor 00699 */ 00700 #ifdef DOXYGENP 00701 template<size_t N, size_t M> class ufmatrix : 00702 public umatrix_tlate<data_t> 00703 #else 00704 template<size_t N, size_t M> class ufmatrix : 00705 public umatrix_tlate<double> 00706 #endif 00707 { 00708 public: 00709 ufmatrix() : umatrix_tlate<double>(N,M) { 00710 } 00711 }; 00712 00713 00714 #ifndef DOXYGENP 00715 } 00716 #endif 00717 00718 #endif 00719 00720 00721
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page