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