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