00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, 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_TENSOR_H 00024 #define O2SCL_TENSOR_H 00025 00026 /** \file tensor.h 00027 \brief File for definitions of tensors 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/umatrix_tlate.h> 00042 #include <o2scl/smart_interp.h> 00043 00044 #ifndef DOXYGENP 00045 namespace o2scl { 00046 #endif 00047 00048 /** 00049 \brief Tensor class with arbitrary dimensions 00050 00051 \todo More complete testing. 00052 00053 \future Could implement arithmetic operators + and - and some 00054 different products. 00055 \future Add slicing to get \ref ovector or \ref omatrix objects 00056 */ 00057 class tensor { 00058 00059 #ifndef DOXYGEN_INTERNAL 00060 00061 protected: 00062 00063 // The data 00064 double *data; 00065 00066 /// A rank-sized array of the sizes of each dimension 00067 size_t *size; 00068 00069 /// Rank 00070 size_t rk; 00071 00072 #endif 00073 00074 public: 00075 00076 /// Create an empty tensor with zero rank 00077 tensor() { 00078 rk=0; 00079 data=0; 00080 size=0; 00081 } 00082 00083 /** 00084 \brief Create a tensor of rank \c rank with sizes given in \c dim 00085 00086 The parameter \c dim must be a pointer to an array of sizes 00087 with length \c rank. If the user requests any of the sizes to 00088 be zero, this constructor will call the error handler, create 00089 an empty tensor, and will allocate no memory. 00090 */ 00091 tensor(size_t rank, size_t *dim) { 00092 for(size_t i=0;i<rk;i++) { 00093 if (dim[i]==0) { 00094 rk=0; 00095 O2SCL_ERR("Requested zero size in tensor::tensor(size_t, size_t *)", 00096 gsl_einval); 00097 } 00098 } 00099 rk=rank; 00100 size=new size_t[rk]; 00101 size_t tot=1; 00102 for(size_t i=0;i<rk;i++) { 00103 size[i]=dim[i]; 00104 tot*=size[i]; 00105 } 00106 data=new double[tot]; 00107 } 00108 00109 virtual ~tensor() { 00110 if (rk>0) { 00111 delete[] size; 00112 delete[] data; 00113 rk=0; 00114 } 00115 } 00116 00117 /// Set the element indexed by \c index to value \c val 00118 virtual int set(size_t *index, double val) { 00119 #if O2SCL_NO_RANGE_CHECK 00120 #else 00121 if (rk==0) { 00122 O2SCL_ERR("Empty tensor in set().",gsl_einval); 00123 return 0; 00124 } 00125 if (index[0]>=size[0]) { 00126 O2SCL_ERR("Index greater than size in set().",gsl_eindex); 00127 return 0; 00128 } 00129 #endif 00130 size_t ix=index[0]; 00131 for(size_t i=1;i<rk;i++) { 00132 #if O2SCL_NO_RANGE_CHECK 00133 #else 00134 if (index[i]>=size[i]) { 00135 O2SCL_ERR("Index greater than size in get().",gsl_eindex); 00136 return 0; 00137 } 00138 #endif 00139 ix*=size[i]; 00140 ix+=index[i]; 00141 } 00142 data[ix]=val; 00143 return 0; 00144 } 00145 00146 /// Get the element indexed by \c index 00147 virtual double &get(size_t *index) { 00148 #if O2SCL_NO_RANGE_CHECK 00149 #else 00150 if (rk==0) { 00151 O2SCL_ERR("Empty tensor in get().",gsl_einval); 00152 return data[0]; 00153 } 00154 if (index[0]>=size[0]) { 00155 O2SCL_ERR("Index greater than size in get().",gsl_eindex); 00156 return data[0]; 00157 } 00158 #endif 00159 size_t ix=index[0]; 00160 for(size_t i=1;i<rk;i++) { 00161 #if O2SCL_NO_RANGE_CHECK 00162 #else 00163 if (index[i]>=size[i]) { 00164 O2SCL_ERR("Index greater than size in get().",gsl_eindex); 00165 return data[0]; 00166 } 00167 #endif 00168 ix*=size[i]; 00169 ix+=index[i]; 00170 } 00171 return data[ix]; 00172 } 00173 00174 00175 /// Get the element indexed by \c index 00176 virtual double const &get(size_t *index) const { 00177 #if O2SCL_NO_RANGE_CHECK 00178 #else 00179 if (rk==0) { 00180 O2SCL_ERR("Empty tensor in get().",gsl_einval); 00181 return data[0]; 00182 } 00183 if (index[0]>=size[0]) { 00184 O2SCL_ERR("Index greater than size in get().",gsl_eindex); 00185 return data[0]; 00186 } 00187 #endif 00188 size_t ix=index[0]; 00189 for(size_t i=1;i<rk;i++) { 00190 #if O2SCL_NO_RANGE_CHECK 00191 #else 00192 if (index[i]>=size[i]) { 00193 O2SCL_ERR("Index greater than size in get().",gsl_eindex); 00194 return data[0]; 00195 } 00196 #endif 00197 ix*=size[i]; 00198 ix+=index[i]; 00199 } 00200 return data[ix]; 00201 } 00202 00203 /** 00204 \brief Fix all but one index to create a vector 00205 00206 This fixes all of the indices to the values given in \c index 00207 except for the index number \c ix, and returns the 00208 corresponding vector, whose length is equal to the size of the 00209 tensor in that index. The value <tt>index[ix]</tt> is ignored. 00210 00211 For example, for a rank 3 tensor allocated with 00212 \code 00213 tensor t; 00214 size_t dim[3]={3,4,5}; 00215 t.tensor_allocate(3,dim); 00216 \endcode 00217 the following code 00218 \code 00219 size_t index[3]={1,0,3}; 00220 ovector_view v=t.vector_slice(index,1); 00221 \endcode 00222 Gives a vector \c v of length 4 which refers to the values 00223 <tt>t(1,0,3)</tt>, <tt>t(1,1,3)</tt>, <tt>t(1,2,3)</tt>, and 00224 <tt>t(1,3,3)</tt>. 00225 */ 00226 ovector_array_stride vector_slice(size_t ix, size_t *index) { 00227 size_t start=index[0]; 00228 if (ix==0) start=0; 00229 for(size_t i=1;i<rk;i++) { 00230 start*=size[i]; 00231 if (i!=ix) start+=index[i]; 00232 } 00233 size_t stride=1; 00234 for(size_t i=ix+1;i<rk;i++) stride*=size[i]; 00235 return ovector_array_stride(size[ix],data+start,stride); 00236 } 00237 00238 /** 00239 \brief Fix all but two indices to create a matrix 00240 00241 This fixes all of the indices to the values given in \c index 00242 except for the index number \c ix and the last index, and 00243 returns the corresponding matrix, whose size is equal to the 00244 size of the tensor in the two indices which are not fixed. 00245 */ 00246 omatrix_array matrix_slice(size_t *index, size_t ix) { 00247 size_t start=index[0], tot=size[0]; 00248 if (ix==0) start=0; 00249 for(size_t i=1;i<rk;i++) { 00250 tot*=size[i]; 00251 start*=size[i]; 00252 if (i!=ix) start+=index[i]; 00253 } 00254 size_t tda=1; 00255 if (ix==rk-1) { 00256 tda=0; 00257 } else { 00258 for(size_t i=ix+1;i<rk;i++) tda*=size[i]; 00259 } 00260 return omatrix_array(tot,data,start,tda,size[ix],size[rk-1]); 00261 } 00262 00263 /// Return the rank of the tensor 00264 virtual int get_rank() { return rk; } 00265 00266 /** 00267 \brief Allocate space for a 00268 tensor of rank \c rank with sizes given in \c dim 00269 00270 The parameter \c dim must be a pointer to an array of sizes 00271 with length \c rank. 00272 00273 If memory was previously allocated, it will be freed before 00274 the new allocation and previously specified grid data will 00275 be lost. 00276 00277 If the user requests any of the sizes to be zero, this 00278 function will call the error handler and will allocate no 00279 memory. If memory was previously allocated, the tensor is left 00280 unmodified and no deallocation is performed. 00281 */ 00282 virtual int tensor_allocate(size_t rank, size_t *dim) { 00283 for(size_t i=0;i<rk;i++) { 00284 if (dim[i]==0) { 00285 O2SCL_ERR_RET 00286 ("Requested zero size in tensor::tensor(size_t, size_t *)", 00287 gsl_einval); 00288 } 00289 } 00290 if (rk>0) tensor_free(); 00291 rk=rank; 00292 size=new size_t[rk]; 00293 size_t tot=1; 00294 for(size_t i=0;i<rk;i++) { 00295 size[i]=dim[i]; 00296 tot*=size[i]; 00297 } 00298 data=new double[tot]; 00299 return 0; 00300 } 00301 00302 /// Free allocated space (also sets rank to zero) 00303 virtual int tensor_free() { 00304 if (rk>0) { 00305 delete[] size; 00306 delete[] data; 00307 rk=0; 00308 } 00309 return 0; 00310 } 00311 00312 /// Returns the size of the ith index 00313 virtual size_t get_size(size_t i) { 00314 if (i<rk) { 00315 return size[i]; 00316 } 00317 O2SCL_ERR_RET("Requested index exceeding rank in get_size()", 00318 gsl_einval); 00319 }; 00320 00321 /// Returns the size of the tensor 00322 virtual size_t total_size() { 00323 if (rk==0) return 0; 00324 size_t tot=1; 00325 for(size_t i=0;i<rk;i++) tot*=size[i]; 00326 return tot; 00327 } 00328 00329 /// Pack the indices into a single array index 00330 size_t pack_indices(size_t *index) { 00331 if (rk==0) { 00332 O2SCL_ERR("Empty tensor in pack_indices().",gsl_einval); 00333 return 0; 00334 } 00335 if (index[0]>=size[0]) { 00336 O2SCL_ERR("Index greater than size in pack_indices().",gsl_eindex); 00337 return 0; 00338 } 00339 size_t ix=index[0]; 00340 for(size_t i=1;i<rk;i++) { 00341 if (index[i]>=size[i]) { 00342 O2SCL_ERR("Index greater than size in pack_indices().",gsl_eindex); 00343 return 0; 00344 } 00345 ix*=size[i]; 00346 ix+=index[i]; 00347 } 00348 return ix; 00349 } 00350 00351 /// Unpack the single array index into indices 00352 int unpack_indices(size_t ix, size_t *index) { 00353 if (ix>total_size()) { 00354 O2SCL_ERR("Index greater than total size in unpack_indices().", 00355 gsl_eindex); 00356 return 0; 00357 } 00358 size_t ix2, sub_size; 00359 for(size_t i=0;i<rk;i++) { 00360 if (i==rk-1) { 00361 index[i]=ix; 00362 } else { 00363 sub_size=1; 00364 for(size_t j=i+1;j<rk;j++) sub_size*=size[j]; 00365 index[i]=ix/sub_size; 00366 // (Remember we're doing integer arithmetic here.) 00367 ix-=sub_size*(ix/sub_size); 00368 } 00369 } 00370 return 0; 00371 } 00372 00373 }; 00374 00375 /** 00376 \brief Tensor class with arbitrary dimensions with a grid 00377 00378 This tensor class allows one to assign the indexes to 00379 numerical scales, so that n-dimensional interpolation can 00380 be performed. To set the grid, use set_grid() and then 00381 interpolation can be done using interpolate(). 00382 00383 \future Only allocate space for grid if it is set 00384 \future Could implement arithmetic operators + and - and some 00385 different products. 00386 */ 00387 class tensor_grid : public tensor { 00388 00389 #ifndef DOXYGEN_INTERNAL 00390 00391 protected: 00392 00393 /// A rank-sized set of arrays for the grid points 00394 double **grd; 00395 00396 /// If true, the grid has been set by the user 00397 bool grid_set; 00398 00399 /// The interpolation manager 00400 base_interp_mgr<double *> *bim1; 00401 00402 /// The subvector interpolation manager 00403 base_interp_mgr<array_const_subvector> *bim2; 00404 00405 #endif 00406 00407 public: 00408 00409 /// Create an empty tensor with zero rank 00410 tensor_grid() : tensor() { 00411 grd=0; 00412 grid_set=false; 00413 bim1=&dim1; 00414 bim2=&dim2; 00415 } 00416 00417 /** 00418 \brief Create a tensor of rank \c rank with sizes given in \c dim 00419 00420 The parameter \c dim must be a pointer to an array of sizes 00421 with length \c rank. If the user requests any of the sizes to 00422 be zero, this constructor will call the error handler, create 00423 an empty tensor, and will allocate no memory. 00424 00425 \future Create a "tensor_grid1" for completeness. 00426 */ 00427 tensor_grid(size_t rank, size_t *dim) : tensor(rank,dim) { 00428 grid_set=false; 00429 for(size_t i=0;i<rk;i++) { 00430 if (dim[i]==0) { 00431 rk=0; 00432 O2SCL_ERR("Requested zero size in tensor::tensor(size_t, size_t *)", 00433 gsl_einval); 00434 } 00435 } 00436 grd=new double *[rk]; 00437 for(size_t i=0;i<rk;i++) { 00438 grd[i]=new double[size[i]]; 00439 } 00440 } 00441 00442 virtual ~tensor_grid() { 00443 if (rk>0) { 00444 for(size_t i=0;i<rk;i++) delete[] grd[i]; 00445 delete[] size; 00446 delete[] data; 00447 rk=0; 00448 } 00449 } 00450 00451 /// Set the element closest to grid point \c grdp to value \c val 00452 virtual int set_val(double *grdp, double val) { 00453 00454 // Find indices 00455 size_t *index=new size_t[rk]; 00456 for(size_t i=0;i<rk;i++) index[i]=lookup_grid(i,grdp[i]); 00457 00458 // Pack 00459 size_t ix=index[0]; 00460 for(size_t i=1;i<rk;i++) { 00461 ix*=size[i]; 00462 ix+=index[i]; 00463 } 00464 00465 // Delete memory for indices 00466 delete[] index; 00467 00468 // Set value 00469 data[ix]=val; 00470 00471 return 0; 00472 } 00473 00474 /// Set the element closest to grid point \c grdp to value \c val 00475 virtual int set_val(double *grdp, double val, double *closest) { 00476 00477 // Find indices 00478 size_t *index=new size_t[rk]; 00479 for(size_t i=0;i<rk;i++) { 00480 index[i]=lookup_grid_val(i,grdp[i],closest[i]); 00481 } 00482 00483 // Pack 00484 size_t ix=index[0]; 00485 for(size_t i=1;i<rk;i++) { 00486 ix*=size[i]; 00487 ix+=index[i]; 00488 } 00489 00490 // Delete memory for indices 00491 delete[] index; 00492 00493 // Set value 00494 data[ix]=val; 00495 00496 return 0; 00497 } 00498 00499 /// Get the element closest to grid point \c grdp 00500 virtual double get_val(double *grdp) { 00501 00502 // Find indices 00503 size_t *index=new size_t[rk]; 00504 for(size_t i=0;i<rk;i++) index[i]=lookup_grid(i,grdp[i]); 00505 00506 // Pack 00507 size_t ix=index[0]; 00508 for(size_t i=1;i<rk;i++) { 00509 ix*=size[i]; 00510 ix+=index[i]; 00511 } 00512 00513 // Delete memory for indices 00514 delete[] index; 00515 00516 // Set value 00517 return data[ix]; 00518 } 00519 00520 /// Get the element closest to grid point \c grdp to value \c val 00521 virtual double get_val(double *grdp, double *closest) { 00522 00523 // Find indices 00524 size_t *index=new size_t[rk]; 00525 for(size_t i=0;i<rk;i++) { 00526 index[i]=lookup_grid_val(i,grdp[i],closest[i]); 00527 } 00528 00529 // Pack 00530 size_t ix=index[0]; 00531 for(size_t i=1;i<rk;i++) { 00532 ix*=size[i]; 00533 ix+=index[i]; 00534 } 00535 00536 // Delete memory for indices 00537 delete[] index; 00538 00539 // Set value 00540 return data[ix]; 00541 } 00542 00543 /** 00544 \brief Set the grid 00545 00546 The parameter \c grid must define the grid, so that \c 00547 val[i][j] is the jth grid point for the ith index. The size 00548 of array \c grid[i] should be given by \c dim[i] where \c dim 00549 was the argument given in the constructor or to the function 00550 \ref tensor_allocate(). 00551 00552 Note that the grid is copied so the function argument may 00553 be destroyed by the user after calling set_grid(). 00554 00555 \future Define a more generic interface for matrix types 00556 00557 */ 00558 virtual int set_grid(double **val) { 00559 for(size_t i=0;i<rk;i++) { 00560 for(size_t j=0;j<size[i];j++) { 00561 grd[i][j]=val[i][j]; 00562 } 00563 } 00564 grid_set=true; 00565 return 0; 00566 } 00567 00568 /** 00569 \brief Allocate space for a tensor of rank \c rank with sizes 00570 given in \c dim 00571 00572 The parameter \c dim must be a pointer to an array of sizes 00573 with length \c rank. 00574 00575 If memory was previously allocated, it will be freed before 00576 the new allocation and previously specified grid data will 00577 be lost. 00578 00579 If the user requests any of the sizes to be zero, this 00580 function will call the error handler and will allocate no 00581 memory. If memory was previously allocated, the tensor is left 00582 unmodified and no deallocation is performed. 00583 */ 00584 virtual int tensor_allocate(size_t rank, size_t *dim) { 00585 for(size_t i=0;i<rk;i++) { 00586 if (dim[i]==0) { 00587 O2SCL_ERR_RET 00588 ("Requested zero size in tensor::tensor(size_t, size_t *)", 00589 gsl_einval); 00590 } 00591 } 00592 if (rk>0) tensor_free(); 00593 rk=rank; 00594 size=new size_t[rk]; 00595 grd=new double *[rk]; 00596 size_t tot=1; 00597 for(size_t i=0;i<rk;i++) { 00598 size[i]=dim[i]; 00599 grd[i]=new double[size[i]]; 00600 tot*=size[i]; 00601 } 00602 data=new double[tot]; 00603 return 0; 00604 } 00605 00606 /// Free allocated space (also sets rank to zero) 00607 virtual int tensor_free() { 00608 if (rk>0) { 00609 for(size_t i=0;i<rk;i++) delete[] grd[i]; 00610 delete[] size; 00611 delete[] grd; 00612 delete[] data; 00613 rk=0; 00614 } 00615 return 0; 00616 } 00617 00618 /// Lookup index for grid closest to \c val 00619 virtual size_t lookup_grid(size_t i, double val) { 00620 if (i<rk && grid_set) { 00621 size_t best=0; 00622 double min=fabs(grd[i][0]-val); 00623 for(size_t j=0;j<size[i];j++) { 00624 if (fabs(grd[i][j]-val)<min) { 00625 best=j; 00626 min=fabs(grd[i][j]-val); 00627 } 00628 } 00629 return best; 00630 } 00631 return 0; 00632 } 00633 00634 /// Lookup index for grid closest to \c val 00635 virtual double get_grid(size_t i, size_t j) { 00636 if (i<rk && grid_set) { 00637 return grd[i][j]; 00638 } 00639 return 0; 00640 } 00641 00642 /// Lookup indices for grid closest to \c val 00643 virtual int lookup_grid(double* vals, size_t *indices) { 00644 for(size_t k=0;k<rk;k++) { 00645 indices[k]=0; 00646 double min=fabs(grd[k][0]-vals[k]); 00647 for(size_t j=0;j<size[k];j++) { 00648 if (fabs(grd[k][j]-vals[k])<min) { 00649 indices[k]=j; 00650 min=fabs(grd[k][j]-vals[k]); 00651 } 00652 } 00653 } 00654 return 0; 00655 } 00656 00657 /// Lookup index for grid closest to \c val, returning the grid point 00658 virtual size_t lookup_grid_val(size_t i, double val, double &val2) { 00659 if (i<rk && grid_set) { 00660 size_t best=0; 00661 double min=fabs(grd[i][0]-val); 00662 val2=grd[i][0]; 00663 for(size_t j=0;j<size[i];j++) { 00664 if (fabs(grd[i][j]-val)<min) { 00665 best=j; 00666 min=fabs(grd[i][j]-val); 00667 val2=grd[i][j]; 00668 } 00669 } 00670 return best; 00671 } 00672 return 0; 00673 } 00674 00675 /// \name Default interpolation managers 00676 //@{ 00677 def_interp_mgr<double *,cspline_interp> dim1; 00678 def_interp_mgr<array_const_subvector,cspline_interp> dim2; 00679 //@} 00680 00681 /// Set interpolation managers 00682 int set_interp(base_interp_mgr<double *> &bi1, 00683 base_interp_mgr<array_const_subvector> &bi2) { 00684 bim1=&bi1; 00685 bim2=&bi2; 00686 return 0; 00687 } 00688 00689 /** 00690 \brief Interpolate values \c vals into the tensor, 00691 returning the result 00692 00693 This is a quick and dirty implementation of n-dimensional 00694 interpolation by recursive application of the 1-dimensional 00695 routine from \ref smart_interp_vec, using the base 00696 interpolation object specified in the template parameter \c 00697 base_interp_t. This will be slow for sufficiently large data 00698 sets. 00699 00700 \future It should be straightforward to improve the scaling 00701 of this algorithm significantly by creating a "window" of 00702 local points around the point of interest. This could 00703 be done easily by constructing an initial subtensor. 00704 */ 00705 virtual double interpolate(double *vals) { 00706 typedef smart_interp_vec<double *,array_const_subvector, 00707 double *, pointer_alloc<double> > interp_t; 00708 00709 if (rk==1) { 00710 00711 sma_interp_vec<double *> si(size[0],grd[0],data); 00712 return si.interp(vals[0]); 00713 00714 } else { 00715 00716 // Get total number of interpolations at this level 00717 size_t ss=1; 00718 for(size_t i=1;i<rk;i++) ss*=size[i]; 00719 00720 // Create space for y vectors and interpolators 00721 double **yvec=new double *[ss]; 00722 interp_t **si=new interp_t *[ss]; 00723 for(size_t i=0;i<ss;i++) yvec[i]=new double[size[0]]; 00724 00725 // Create space for interpolation results 00726 tensor_grid tdat; 00727 tdat.tensor_allocate(rk-1,size+1); 00728 00729 // Set grid for temporary tensor 00730 tdat.set_grid(grd+1); 00731 00732 // Create starting coordinate and counter 00733 size_t *co=new size_t[rk]; 00734 for(size_t i=0;i<rk;i++) co[i]=0; 00735 size_t cnt=0; 00736 00737 // Loop over every interpolation 00738 bool done=false; 00739 while(done==false) { 00740 00741 // Fill yvector with the appropriate data 00742 for(size_t i=0;i<size[0];i++) { 00743 co[0]=i; 00744 yvec[cnt][i]=get(co); 00745 } 00746 00747 si[cnt]=new interp_t(*bim1,*bim2,size[0],grd[0],yvec[cnt]); 00748 00749 tdat.set(co+1,si[cnt]->interp(vals[0])); 00750 00751 // Go to next interpolation 00752 cnt++; 00753 co[rk-1]++; 00754 // carry if necessary 00755 for(int j=rk-1;j>0;j--) { 00756 if (co[j]>=size[j]) { 00757 co[j]=0; 00758 co[j-1]++; 00759 } 00760 } 00761 00762 // Test if done 00763 if (cnt==ss) done=true; 00764 00765 // End of while loop 00766 } 00767 00768 // Now call the next level of interpolation 00769 double res=tdat.interpolate(vals+1); 00770 00771 tdat.tensor_free(); 00772 for(size_t i=0;i<ss;i++) { 00773 delete[] yvec[i]; 00774 delete si[i]; 00775 } 00776 delete[] co; 00777 delete[] si; 00778 delete[] yvec; 00779 00780 return res; 00781 } 00782 } 00783 }; 00784 00785 /** 00786 \brief Rank 1 tensor 00787 */ 00788 class tensor1 : public tensor { 00789 public: 00790 00791 /// Create an empty tensor 00792 tensor1() : tensor() {} 00793 00794 /// Create a rank 1 tensory of size \c sz 00795 tensor1(size_t sz) : tensor(1,&sz) {} 00796 00797 /// Get the element indexed by \c ix 00798 virtual double &get(size_t ix) { return tensor::get(&ix); } 00799 00800 /// Get the element indexed by \c ix 00801 virtual const double &get(size_t ix) const { return tensor::get(&ix); } 00802 00803 /// Set the element indexed by \c index to value \c val 00804 virtual int set(size_t index, double val) 00805 { return tensor::set(&index,val); } 00806 00807 /// Get an element using array-like indexing 00808 virtual double &operator[](size_t ix) { return this->data[ix]; } 00809 00810 /// Get an element using operator() 00811 virtual double &operator()(size_t ix) { return this->data[ix]; } 00812 }; 00813 00814 /** 00815 \brief Rank 2 tensor 00816 */ 00817 class tensor2 : public tensor { 00818 public: 00819 00820 /// Create an empty tensor 00821 tensor2() : tensor() {} 00822 00823 /// Create a rank 2 tensor of size \c (sz,sz2) 00824 tensor2(size_t sz, size_t sz2) : tensor() { 00825 this->rk=2; 00826 this->size=new size_t[2]; 00827 this->size[0]=sz; 00828 this->size[1]=sz2; 00829 size_t tot=sz*sz2; 00830 this->data=new double[tot]; 00831 } 00832 00833 /// Get the element indexed by \c (ix1,ix2) 00834 virtual double &get(size_t ix1, size_t ix2) { 00835 size_t sz[2]={ix1,ix2}; 00836 return tensor::get(sz); 00837 } 00838 00839 /// Get the element indexed by \c (ix1,ix2) 00840 virtual const double &get(size_t ix1, size_t ix2) const { 00841 size_t sz[2]={ix1,ix2}; 00842 return tensor::get(sz); 00843 } 00844 00845 /// Set the element indexed by \c (ix1,ix2) to value \c val 00846 virtual int set(size_t ix1, size_t ix2, double val) { 00847 size_t sz[2]={ix1,ix2}; 00848 return tensor::set(sz,val); 00849 } 00850 00851 /// Get the element indexed by \c (ix1,ix2) 00852 virtual double &operator()(size_t ix, size_t iy) 00853 { return this->data[ix*this->size[1]+iy]; } 00854 }; 00855 00856 /** 00857 \brief Rank 2 tensor with a grid 00858 */ 00859 class tensor_grid2 : public tensor_grid { 00860 00861 public: 00862 00863 /// Create an empty tensor 00864 tensor_grid2() : tensor_grid() {} 00865 00866 /// Create a rank 2 tensor of size \c (sz,sz2,sz3) 00867 tensor_grid2(size_t sz, size_t sz2) : tensor_grid() { 00868 this->rk=2; 00869 this->size=new size_t[2]; 00870 this->grd=new double *[2]; 00871 this->size[0]=sz; 00872 this->size[1]=sz2; 00873 this->grd[0]=new double[sz]; 00874 this->grd[1]=new double[sz2]; 00875 size_t tot=sz*sz2; 00876 this->data=new double[tot]; 00877 this->grid_set=false; 00878 } 00879 00880 virtual ~tensor_grid2() { 00881 if (this->rk>0) { 00882 for(size_t i=0;i<this->rk;i++) { 00883 delete[] this->grd[i]; 00884 } 00885 delete[] this->size; 00886 delete[] this->grd; 00887 delete[] this->data; 00888 this->rk=0; 00889 } 00890 } 00891 00892 /// Get the element indexed by \c (ix1,ix2,ix3) 00893 virtual double &get(size_t ix1, size_t ix2) { 00894 size_t sz[2]={ix1,ix2}; 00895 return tensor_grid ::get(sz); 00896 } 00897 00898 /// Get the element indexed by \c (ix1,ix2,ix3) 00899 virtual const double &get(size_t ix1, size_t ix2) const { 00900 size_t sz[2]={ix1,ix2}; 00901 return tensor_grid ::get(sz); 00902 } 00903 00904 /// Set the element indexed by \c (ix1,ix2,ix3) to value \c val 00905 virtual int set(size_t ix1, size_t ix2, double val) { 00906 size_t sz[2]={ix1,ix2}; 00907 return tensor_grid ::set(sz,val); 00908 } 00909 }; 00910 00911 /** 00912 \brief Rank 3 tensor 00913 */ 00914 class tensor3 : public tensor { 00915 public: 00916 00917 /// Create an empty tensor 00918 tensor3() : tensor() {} 00919 00920 /// Create a rank 3 tensor of size \c (sz,sz2,sz3) 00921 tensor3(size_t sz, size_t sz2, size_t sz3) : tensor() { 00922 this->rk=3; 00923 this->size=new size_t[3]; 00924 this->size[0]=sz; 00925 this->size[1]=sz2; 00926 this->size[2]=sz3; 00927 size_t tot=sz*sz2*sz3; 00928 this->data=new double[tot]; 00929 } 00930 00931 /// Get the element indexed by \c (ix1,ix2,ix3) 00932 virtual double &get(size_t ix1, size_t ix2, size_t ix3) { 00933 size_t sz[3]={ix1,ix2,ix3}; 00934 return tensor::get(sz); 00935 } 00936 00937 /// Get the element indexed by \c (ix1,ix2,ix3) 00938 virtual const double &get(size_t ix1, size_t ix2, size_t ix3) const { 00939 size_t sz[3]={ix1,ix2,ix3}; 00940 return tensor::get(sz); 00941 } 00942 00943 /// Set the element indexed by \c (ix1,ix2,ix3) to value \c val 00944 virtual int set(size_t ix1, size_t ix2, size_t ix3, double val) { 00945 size_t sz[3]={ix1,ix2, ix3}; 00946 return tensor::set(sz,val); 00947 } 00948 }; 00949 00950 /** 00951 \brief Rank 3 tensor with a grid 00952 */ 00953 class tensor_grid3 : public tensor_grid { 00954 00955 public: 00956 00957 /// Create an empty tensor 00958 tensor_grid3() : tensor_grid () {} 00959 00960 /// Create a rank 3 tensor of size \c (sz,sz2,sz3) 00961 tensor_grid3(size_t sz, size_t sz2, size_t sz3) : tensor_grid () { 00962 this->rk=3; 00963 this->size=new size_t[3]; 00964 this->grd=new double *[3]; 00965 this->size[0]=sz; 00966 this->size[1]=sz2; 00967 this->size[2]=sz3; 00968 this->grd[0]=new double[sz]; 00969 this->grd[1]=new double[sz2]; 00970 this->grd[2]=new double[sz3]; 00971 size_t tot=sz*sz2*sz3; 00972 this->data=new double[tot]; 00973 this->grid_set=false; 00974 } 00975 00976 virtual ~tensor_grid3() { 00977 if (this->rk>0) { 00978 for(size_t i=0;i<this->rk;i++) { 00979 delete[] this->grd[i]; 00980 } 00981 delete[] this->size; 00982 delete[] this->grd; 00983 delete[] this->data; 00984 this->rk=0; 00985 } 00986 } 00987 00988 /// Get the element indexed by \c (ix1,ix2,ix3) 00989 virtual double &get(size_t ix1, size_t ix2, size_t ix3) { 00990 size_t sz[3]={ix1,ix2,ix3}; 00991 return tensor_grid ::get(sz); 00992 } 00993 00994 /// Get the element indexed by \c (ix1,ix2,ix3) 00995 virtual const double &get(size_t ix1, size_t ix2, size_t ix3) const { 00996 size_t sz[3]={ix1,ix2,ix3}; 00997 return tensor_grid ::get(sz); 00998 } 00999 01000 /// Set the element indexed by \c (ix1,ix2,ix3) to value \c val 01001 virtual int set(size_t ix1, size_t ix2, size_t ix3, double val) { 01002 size_t sz[3]={ix1,ix2, ix3}; 01003 return tensor_grid ::set(sz,val); 01004 } 01005 }; 01006 01007 /** 01008 \brief Rank 4 tensor 01009 */ 01010 class tensor4 : public tensor { 01011 01012 public: 01013 01014 /// Create an empty tensor 01015 tensor4() : tensor() {} 01016 01017 /// Create a rank 4 tensor of size \c (sz,sz2,sz3,sz4) 01018 tensor4(size_t sz, size_t sz2, size_t sz3, size_t sz4) : 01019 tensor() { 01020 this->rk=4; 01021 this->size=new size_t[4]; 01022 this->size[0]=sz; 01023 this->size[1]=sz2; 01024 this->size[2]=sz3; 01025 this->size[3]=sz4; 01026 size_t tot=sz*sz2*sz3*sz4; 01027 this->data=new double[tot]; 01028 } 01029 01030 /// Get the element indexed by \c (ix1,ix2,ix3,ix4) 01031 virtual double &get(size_t ix1, size_t ix2, size_t ix3, size_t ix4) { 01032 size_t sz[4]={ix1,ix2,ix3,ix4}; 01033 return tensor::get(sz); 01034 } 01035 01036 /// Get the element indexed by \c (ix1,ix2,ix3,ix4) 01037 virtual const double &get(size_t ix1, size_t ix2, size_t ix3, 01038 size_t ix4) const { 01039 size_t sz[4]={ix1,ix2,ix3,ix4}; 01040 return tensor::get(sz); 01041 } 01042 01043 /// Set the element indexed by \c (ix1,ix2,ix3,ix4) to value \c val 01044 virtual int set(size_t ix1, size_t ix2, size_t ix3, size_t ix4, 01045 double val) { 01046 size_t sz[4]={ix1,ix2,ix3,ix4}; 01047 return tensor::set(sz,val); 01048 } 01049 }; 01050 01051 /** 01052 \brief Rank 4 tensor with a grid 01053 */ 01054 class tensor_grid4 : public tensor_grid { 01055 01056 public: 01057 01058 /// Create an empty tensor 01059 tensor_grid4() : tensor_grid () {} 01060 01061 /// Create a rank 4 tensor of size \c (sz,sz2,sz3,sz4) 01062 tensor_grid4(size_t sz, size_t sz2, size_t sz3, 01063 size_t sz4) : tensor_grid () { 01064 this->rk=4; 01065 this->size=new size_t[4]; 01066 this->grd=new double *[4]; 01067 this->size[0]=sz; 01068 this->size[1]=sz2; 01069 this->size[2]=sz3; 01070 this->size[3]=sz4; 01071 this->grd[0]=new double[sz]; 01072 this->grd[1]=new double[sz2]; 01073 this->grd[2]=new double[sz3]; 01074 this->grd[3]=new double[sz4]; 01075 size_t tot=sz*sz2*sz3*sz4; 01076 this->data=new double[tot]; 01077 this->grid_set=false; 01078 } 01079 01080 virtual ~tensor_grid4() { 01081 if (this->rk>0) { 01082 for(size_t i=0;i<this->rk;i++) { 01083 delete[] this->grd[i]; 01084 } 01085 delete[] this->size; 01086 delete[] this->grd; 01087 delete[] this->data; 01088 this->rk=0; 01089 } 01090 } 01091 01092 /// Get the element indexed by \c (ix1,ix2,ix3,ix4) 01093 virtual double &get(size_t ix1, size_t ix2, size_t ix3, size_t ix4) { 01094 size_t sz[4]={ix1,ix2,ix3,ix4}; 01095 return tensor_grid ::get(sz); 01096 } 01097 01098 /// Get the element indexed by \c (ix1,ix2,ix3,ix4) 01099 virtual const double &get(size_t ix1, size_t ix2, size_t ix3, 01100 size_t ix4) const { 01101 size_t sz[4]={ix1,ix2,ix3,ix4}; 01102 return tensor_grid ::get(sz); 01103 } 01104 01105 /// Set the element indexed by \c (ix1,ix2,ix3,ix4) to value \c val 01106 virtual int set(size_t ix1, size_t ix2, size_t ix3, size_t ix4, 01107 double val) { 01108 size_t sz[4]={ix1,ix2,ix3,ix4}; 01109 return tensor_grid ::set(sz,val); 01110 } 01111 }; 01112 01113 #ifndef DOXYGENP 01114 } 01115 #endif 01116 01117 #endif 01118 01119 01120
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