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