00001 // SuperMix version 1.0 C++ source file 00002 // 00003 // Copyright (c) 1999 California Institute of Technology. 00004 // All rights reserved. 00005 // 00006 // Redistribution and use in source and binary forms for noncommercial 00007 // purposes are permitted provided that the above copyright notice and 00008 // this paragraph are duplicated in all such forms and that any 00009 // documentation and other materials related to such distribution and 00010 // use acknowledge that the software was developed by California 00011 // Institute of Technology. Redistribution and/or use in source or 00012 // binary forms is not permitted for any commercial purpose. Use of 00013 // this software does not include a permitted use of the Institute's 00014 // name or trademark for any purpose. 00015 // 00016 // DISCLAIMER: 00017 // THIS SOFTWARE AND/OR RELATED MATERIALS ARE PROVIDED "AS-IS" WITHOUT 00018 // WARRANTY OF ANY KIND INCLUDING ANY WARRANTIES OF PERFORMANCE OR 00019 // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE OR PURPOSE (AS SET 00020 // FORTH IN UCC 23212-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE 00021 // LICENSED PRODUCT, HOWEVER USED. IN NO EVENT SHALL CALTECH/JPL BE 00022 // LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING BUT NOT LIMITED TO 00023 // INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, INCLUDING ECONOMIC 00024 // DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF 00025 // WHETHER CALTECH/JPL SHALL BE ADVISED, HAVE REASON TO KNOW, OR IN 00026 // FACT SHALL KNOW OF THE POSSIBILITY. THE USER BEARS ALL RISK 00027 // RELATING TO QUALITY AND PERFORMANCE OF THE SOFTWARE AND/OR RELATED 00028 // MATERIALS. 00029 // 00030 // ******************************************************************** 00031 // Definitions of functions in class interpolator<> 00032 // 00033 // F. Rice 4/9/99 00034 // ******************************************************************** 00035 00036 #include "error.h" 00037 #include <algorithm> 00038 00039 // -------------------------------------------------------------------- 00040 // used by search routines: true if x(d1) < d2, where d1 is an (x,y) pair: 00041 00042 template < class Y > inline bool operator < 00043 (const pair<double,Y> & d1, const double & d2) 00044 { return d1.first < d2; } 00045 00046 00047 // -------------------------------------------------------------------- 00048 // constructors; clear(); operator = 00049 00050 template < class Y_type > inline 00051 interpolator<Y_type>::interpolator() 00052 : ready_(false), no_warn_(false), type_(SPLINE), user_ls(false), user_rs(false) 00053 { } 00054 00055 00056 template < class Y_type > inline 00057 interpolator<Y_type>::interpolator(const interpolator<Y_type> & f) 00058 : data(f.data), aux(f.aux), table(), 00059 ready_(false), no_warn_(f.no_warn_), type_(f.type_), 00060 user_ls(f.user_ls), user_rs(f.user_rs) 00061 { 00062 if (user_ls) lslope = f.lslope; 00063 if (user_rs) rslope = f.rslope; 00064 if (f.ready_) build(); 00065 } 00066 00067 00068 template < class Y_type > inline 00069 interpolator<Y_type> & interpolator<Y_type>::clear() 00070 { 00071 // conditions on exit from clear(): 00072 // (1) data and aux are empty 00073 // (2) table is empty 00074 // (3) ready() == false, user_ls == false, user_rs == false, type_ = SPLINE 00075 00076 data.erase(data.begin(), data.end()); 00077 aux.erase(aux.begin(), aux.end()); 00078 table.erase(table.begin(), table.end()); 00079 ready_ = user_ls = user_rs = false; 00080 type_ = SPLINE; 00081 00082 return *this; 00083 } 00084 00085 00086 template < class Y_type > inline 00087 interpolator<Y_type> & interpolator<Y_type>::operator = 00088 (const interpolator<Y_type> & f) 00089 { 00090 data = f.data; aux = f.aux; table.erase(table.begin(),table.end()); 00091 ready_ = false; no_warn_ = f.no_warn_; type_ = f.type_; 00092 user_ls = f.user_ls; user_rs = f.user_rs; 00093 if (user_ls) lslope = f.lslope; 00094 if (user_rs) rslope = f.rslope; 00095 if (f.ready_) build(); 00096 return *this; 00097 } 00098 00099 00100 // -------------------------------------------------------------------- 00101 // set-up routines: add(), type(), left_slope(), right_slope() 00102 00103 template < class Y_type > inline 00104 interpolator<Y_type> & interpolator<Y_type>::add(const double x, const Y_type & y) 00105 { 00106 static data_type temp; // declared static so allocation occurs once 00107 temp.first = x, temp.second = y; 00108 00109 // invariants on entry to and exit from add(): 00110 // (1) data is sorted by x values, lowest x first, all x's unique 00111 // (2) aux has the same size as data 00112 00113 if ( data.size() == 0 || data.back() < x ) { 00114 // new data just goes to the back 00115 data.push_back(temp); // just add new data to back 00116 } 00117 else { 00118 // need to enter data somewhere else 00119 data_iter j = lower_bound(data.begin(), data.end(), x); 00120 if ((j->first) == x) // a duplicate x value 00121 error::fatal("x values input to interpolator are not all unique."); 00122 data.insert(j, temp); // maintain invariant (1) 00123 } 00124 00125 aux.push_front(temp); // now restore invariant (2), using temp as junk 00126 00127 return *this; 00128 } 00129 00130 template < class Y_type > inline 00131 interpolator<Y_type> & interpolator<Y_type>::add(const interpolator<Y_type> & Z) 00132 { 00133 data_type temp; 00134 double & x = temp.first; 00135 Y_type & y = temp.second; 00136 00137 // loop through the supplied interpolator's data list 00138 for(interpolator::const_data_iter i = Z.data.begin(); i != Z.data.end(); ++i) { 00139 x = i->first; y = i->second; 00140 00141 // invariants on entry to and exit from add(): 00142 // (1) data is sorted by x values, lowest x first, all x's unique 00143 // (2) aux has the same size as data 00144 00145 if ( data.size() == 0 || data.back() < x ) { 00146 // new data just goes to the back 00147 data.push_back(temp); // just add new data to back 00148 } 00149 else { 00150 // need to enter data somewhere else 00151 data_iter j = lower_bound(data.begin(), data.end(), x); 00152 if ((j->first) != x) // not a duplicate x value 00153 data.insert(j, temp); // maintain invariant (1) 00154 } 00155 00156 aux.push_front(temp); // now restore invariant (2), using temp as junk 00157 } 00158 00159 return *this; 00160 } 00161 00162 00163 template < class Y_type > inline 00164 interpolator<Y_type> & interpolator<Y_type>::type(int t) 00165 { 00166 ready_ = false; // must rebuild before using 00167 switch(t) { 00168 default: 00169 case LINEAR: { type_ = LINEAR; break; } 00170 case SPLINE: { type_ = SPLINE; break; } 00171 } 00172 return *this; 00173 } 00174 00175 00176 template < class Y_type > inline 00177 interpolator<Y_type> & interpolator<Y_type>::left_slope(const Y_type & y) 00178 { lslope = y; user_ls = true; ready_ = false; return *this; } 00179 00180 00181 template < class Y_type > inline 00182 interpolator<Y_type> & interpolator<Y_type>::right_slope(const Y_type & y) 00183 { rslope = y; user_rs = true; ready_ = false; return *this; } 00184 00185 00186 // -------------------------------------------------------------------- 00187 // build routines: build(), build_linear(), build_spline() 00188 00189 00190 template < class Y_type > inline 00191 interpolator<Y_type> & interpolator<Y_type>::build() 00192 { 00193 // assumed conditions on entry to build() 00194 // (1) data.size() == aux.size() 00195 // (2) data is sorted by x with all x's unique 00196 // 00197 // conditions on entry for build() to do anything useful 00198 // (1) data and aux each have size() > 1 00199 // 00200 // conditions on successful exit from build(): 00201 // (1) table, data and aux all have the same size() > 1 00202 // (2) ready() == 1 00203 // and for all i (except the last i for (6)) 00204 // (3) table[i].first == data[i].first == x[i] 00205 // (4) table[i].second.first == data.begin()+i => (x[i],y[i]) 00206 // (5) table[i].second.second == aux.begin()+i => (dx[i],yp[i]) 00207 // (6) (aux.begin()+i)->first 00208 // == (data.begin()+i+1)->first - (data.begin()+i)->first 00209 // == dx[i] = x[i+1]-x[i] 00210 00211 data_list::size_type size = data.size(); 00212 00213 if (size != aux.size()) 00214 error::fatal("Internal error in interpolator: " 00215 "internal tables inconsistent"); 00216 00217 if (size <= 1) { 00218 error::warning("Not enough data to interpolate in interpolator. " 00219 "Add more data and build again."); 00220 return *this; 00221 } 00222 00223 // passed the tests, so here goes: 00224 00225 table.erase(table.begin(), table.end()); // clear out old table 00226 table.reserve(size); // and get enough space for new 00227 00228 data_iter i_data = data.begin(), i_aux = aux.begin(); 00229 data_list::size_type i = 0; // counts elements we've processed 00230 double x; 00231 entry t; 00232 while ( ++i < size ) { // loop over all but the final entry 00233 x = i_data->first; // x[i] value here 00234 t.first = x; t.second.first = i_data; t.second.second = i_aux; 00235 table.push_back(t); 00236 00237 // The next line computes aux[i].first = x[i+1] - x[i], incrementing iterators. 00238 (i_aux++)->first = (++i_data)->first - x; 00239 00240 } // while 00241 00242 // now i_data and i_aux point to the final entries 00243 t.first = i_data->first; t.second.first = i_data; t.second.second = i_aux; 00244 table.push_back(t); 00245 00246 // processing of the aux Y data here 00247 switch (type_) { 00248 case LINEAR: { build_linear(); break; } 00249 case SPLINE: { build_spline(); break; } 00250 default: 00251 { error::fatal("Unknown interpolation type in interpolator."); } 00252 } 00253 00254 ready_ = true; 00255 return *this; 00256 } 00257 00258 00259 template < class Y_type > inline 00260 void interpolator<Y_type>::build_linear() 00261 { 00262 // aux Y values contain Y' to next point, to speed up interpolations 00263 // Endpoint slopes are calculated and stored in lslope, rslope if required. 00264 00265 // convenient readablility macros: 00266 #define Y(i) ((i)->second.first->second) 00267 #define Yp(i) ((i)->second.second->second) 00268 #define Dx(i) ((i)->second.second->first) 00269 00270 table_iter i, last = table.end() - 1; 00271 for (i = table.begin(); i != last; ++i) { 00272 Yp(i) = Y(i+1); Yp(i) -= Y(i); Yp(i) *= 1.0/Dx(i); 00273 } 00274 00275 // left extrapolation slope value 00276 if (!user_ls) lslope = Yp(table.begin()); 00277 00278 // right extrapolation slope value 00279 if (!user_rs) rslope = Yp(last-1); 00280 00281 #undef Y 00282 #undef Yp 00283 #undef Dx 00284 } 00285 00286 00287 template < class Y_type > inline 00288 void interpolator<Y_type>::build_spline() 00289 { 00290 // the aux Y[i] will hold Y''(x[i]) for the cubic spline interpolation. 00291 // boundary conditions: if an endpoint slope is specified, use it; otherwise 00292 // set Y'' at the endpoint to 0. The Y(x[i]) and the continuity of Y'' now 00293 // give a tridiagonal set of equations for the Y''[i] like: 00294 // a[i]*Y''[i-1] + b[i]*Y''[i] + c[i]*Y''[i+1] == r[i] 00295 // Note that the a,b,c are scalars (double); the r are Y_type 00296 // 00297 // This algorithm is a highly modified form of that in Numerical Recipes. 00298 00299 static vector<double> c; // holds the -c[i]; static avoids reallocation, 00300 // so multiple builds are faster 00301 c.empty(); c.reserve(table.size()); 00302 00303 index i; 00304 index last = table.size()-1; // the last data element 00305 00306 // convenient readablility macros: 00307 #define Y(i) (table[(i)].second.first->second) 00308 #define Yp(i) (table[(i)].second.second->second) 00309 #define Dx(i) (table[(i)].second.second->first) 00310 #define C(i) (c[(i)]) 00311 #define R(i) (Yp(i)) 00312 00313 // The equations relating the various y''[i] form the following tridiagonal system, 00314 // for 0 < i < table.size() (first eqn (i == 0) comes from boundary condition): 00315 // a y''[i-1] + b y''[i] + c y''[i+1] = r 00316 // where: 00317 // a = (x[i]-x[i-1])/(x[i+1]-x[i-1]) 00318 // b = 2 00319 // c = (x[i+1]-x[i])/(x[i+1]-x[i-1]) 00320 // r = 6((y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]))/(x[i+1]-x[i-1]) 00321 00322 // The first step: diagonalize the system using Gaussian elimination: 00323 // invariants in the elimination loop, 0 <= j < i < table.size()-1 00324 // (1) a[j] == 0 00325 // (2) b[j] == 1 00326 // (3) C(j) == -c[j] ( use vector c to temporarily hold the -c[j] ) 00327 // (4) Yp(j) == r[j] ( use the aux Y list to temporarily hold the r[j] ) 00328 // (5) b[i] == 2 (a literal constant) at start of each iteration i 00329 // 00330 // Also recall that the Dx(i) == x[i+1]-x[i], stored in aux X values. 00331 00332 // set up the equation for i == 0; (b[0] == 1, c[0] == -C(0), r[0] == R(0)): 00333 if (user_ls) { 00334 C(0) = -0.5; 00335 R(0) = Y(1); R(0) -= Y(0); R(0) *= (1.0/Dx(0)); // r = linear slope between points 00336 R(0) -= lslope; // subtract off user-specified slope 00337 R(0) *= (3.0/Dx(0)); // this is the final r[0] 00338 } 00339 else { 00340 R(0) *= (C(0) = 0.0); // the natural spline: Y''[0] == 0 ( b y''[0] == 0; b == 1 ) 00341 } 00342 00343 double b, a; 00344 Y_type m1, m2; 00345 m1 = Y(1); m1 -= Y(0); m1 *= 6.0/Dx(0); // 6 * slope from point 0 to 1 00346 for (i = 1; i < last; ++i) { 00347 // the initial a, b, c, r for row i: 00348 a = 1.0/(Dx(i)+Dx(i-1)); // temporarily == 1/(x[i+1]-x[i-1]) 00349 m2 = Y(i+1); m2 -= Y(i); m2 *= 6.0/Dx(i); // 6 * slope from i to i+1 00350 R(i) = m2; R(i) -= m1; R(i) *= a; // initial r (m1=m2 from the last iter) 00351 m1 = m2; // for the next iteration 00352 a *= Dx(i-1); // == (x[i]-x[i-1])/(x[i+1]-x[i-1]) 00353 b = 2.0; 00354 C(i) = a - 1.0; // == -(x[i+1]-x[i])/(x[i+1]-x[i-1]) 00355 00356 // now the Gaussian elimiation step (b[i-1] == 1 from the loop invariants): 00357 b += a*C(i-1); // b[i] = b[i] - a[i]*c[i-1]; now a[i] == 0 00358 m2 = R(i-1); m2 *= -a; // avoids a Y_type temporary allocation in next line 00359 R(i) += m2; // r[i] = r[i] - a[i]*r[i-1] 00360 // c[i] = c[i] - a[i]*0 (tridiagonal), so no change 00361 b = 1.0/b; // to multiply instead of divide below 00362 C(i) *= b; // normalize so b[i] == 1 00363 R(i) *= b; // normalize so b[i] == 1 00364 } 00365 00366 // Gaussian elimination and back substitution of the last row, where there is no C[i] 00367 if (user_rs) { 00368 Yp(last) = rslope; Yp(last) *= 6.0; 00369 Yp(last) -= m1; // m1 == 6*slope from previous point 00370 Yp(last) *= 1.0/Dx(last-1); 00371 Yp(last) -= R(last-1); 00372 Yp(last) *= 1.0/(2.0 + C(last-1)); 00373 } 00374 else { 00375 Yp(last) *= 0.0; // the natural spline: Y''[last] == 0 00376 } 00377 00378 // back substitution of the remaining rows 00379 for (i = last; i > 0; --i) { 00380 m2 = Yp(i); m2 *= C(i-1); 00381 Yp(i-1) += m2; // remember, C(j) == -c for jth row 00382 } 00383 00384 // now set lslope and rslope if necessary 00385 if (!user_ls) { 00386 lslope = Y(0); lslope *= -1.0; lslope += Y(1); lslope *= 1.0/Dx(0); // slope fm 0 to 1 00387 m2 = Yp(0); m2 *= 2.0; m2 += Yp(1); m2 *= -Dx(0)/6.0; 00388 lslope += m2; 00389 } 00390 if (!user_rs) { 00391 rslope = Y(last-1); rslope *= -1.0; 00392 rslope += Y(last); rslope *= 1.0/Dx(last-1); // slope fm last-1 to last 00393 m2 = Yp(last); m2 *= 2.0; m2 += Yp(last-1); m2 *= Dx(last-1)/6.0; 00394 rslope += m2; 00395 } 00396 00397 #undef Y 00398 #undef Yp 00399 #undef Dx 00400 #undef C 00401 #undef R 00402 } 00403 00404 00405 // -------------------------------------------------------------------- 00406 // interpolation routines: (), linear(), spline(), lextrapolate(), rextrapolate() 00407 // prime(), val_prime(), prime_linear(), prime_spline() 00408 00409 template < class Y_type > inline 00410 Y_type interpolator<Y_type>::operator ()(double x) const 00411 { 00412 if (!ready_) 00413 error::fatal("Must build interpolator before use."); 00414 00415 // attempt to find where in table to interpolate: 00416 const const_table_iter j = lower_bound(table.begin(), table.end(), x); // table[j] >= x; 00417 00418 // check if extrapolation is needed, else perform the interpolation 00419 if (j == table.begin()) { 00420 lextrapolate(x); 00421 if (!no_warn_ && x < j->first) 00422 error::warning("Interpolator extrapolating beyond range of data points."); 00423 } 00424 else if (j == table.end()) { 00425 rextrapolate(x); 00426 if (!no_warn_) 00427 error::warning("Interpolator extrapolating beyond range of data points."); 00428 } 00429 else { 00430 index i = (j - table.begin()) - 1; // now i is such that: x[i] < x <= x[i+1] 00431 switch (type_) { 00432 case LINEAR: { linear(i,x); break; } 00433 case SPLINE: { spline(i,x); break; } 00434 default: 00435 { error::fatal("Unknown interpolation type in interpolator."); } 00436 } 00437 } 00438 00439 return result; 00440 } 00441 00442 00443 template < class Y_type > inline 00444 void interpolator<Y_type>::linear 00445 (interpolator<Y_type>::index i, double x, Y_type & r) const 00446 { 00447 r = table[i].second.second->second; // Y'[i] 00448 r *= x - table[i].first; // Y'[i]*(x - x[i]) 00449 r += table[i].second.first->second; // Y[i] + Y'[i]*(x - x[i]) 00450 } 00451 00452 00453 template < class Y_type > inline 00454 void interpolator<Y_type>::spline 00455 (interpolator<Y_type>::index i, double x, Y_type & r) const 00456 { 00457 double D = x - table[i].first; // D == x - x[i] 00458 double Do = table[i].second.second->first; // Do == x[i+1] - x[i] 00459 double A = D/Do, B = 1.0 - A; 00460 00461 Y_type & T1 = r; // T1 aliases r, and will hold result 00462 T1 = table[i].second.second->second; // T1 == Y''[i] 00463 Y_type T2(table[i+1].second.second->second); // T2 == Y''[i+1] 00464 00465 T1 *= -Do*Do*A*(B+1)/6.0; T2 *= -Do*Do*B*(A+1)/6.0; 00466 T1 += table[i].second.first->second; T1 *= B; 00467 T2 += table[i+1].second.first->second; T2 *= A; 00468 T1 += T2; // T1 has the result 00469 } 00470 00471 00472 template < class Y_type > inline 00473 void interpolator<Y_type>::lextrapolate(double x, Y_type & r) const 00474 { 00475 r = lslope; 00476 r *= (x - table[0].first); 00477 r += table[0].second.first->second; 00478 } 00479 00480 00481 template < class Y_type > inline 00482 void interpolator<Y_type>::rextrapolate(double x, Y_type & r) const 00483 { 00484 r = rslope; 00485 index last = table.size() - 1; 00486 r *= (x - table[last].first); 00487 r += table[last].second.first->second; 00488 } 00489 00490 00491 template < class Y_type > inline 00492 Y_type interpolator<Y_type>::prime(double x) const 00493 { 00494 if (!ready_) 00495 error::fatal("Must build interpolator before use."); 00496 00497 // attempt to find where in table to interpolate: 00498 const const_table_iter j = lower_bound(table.begin(), table.end(), x); // table[j] >= x; 00499 00500 // check if an extrapolation, else perform the interpolation 00501 if (j == table.begin()) { 00502 result = lslope; // linear extrapolation has a constant slope 00503 if (!no_warn_ && x < j->first) 00504 error::warning("Interpolator extrapolating beyond range of data points."); 00505 } 00506 else if (j == table.end()) { 00507 result = rslope; 00508 if (!no_warn_) 00509 error::warning("Interpolator extrapolating beyond range of data points."); 00510 } 00511 else { 00512 index i = (j - table.begin()) - 1; // now i is such that: x[i] < x <= x[i+1] 00513 switch (type_) { 00514 case LINEAR: { prime_linear(i,x); break; } 00515 case SPLINE: { prime_spline(i,x); break; } 00516 default: 00517 { error::fatal("Unknown interpolation type in interpolator."); } 00518 } 00519 } 00520 00521 return result; 00522 } 00523 00524 00525 template < class Y_type > inline 00526 void interpolator<Y_type>::prime_linear 00527 (interpolator<Y_type>::index i, double x, Y_type & r) const 00528 { 00529 // convenient readablility macros: 00530 #define Y(i) (table[(i)].second.first->second) 00531 #define Yp(i) (table[(i)].second.second->second) 00532 #define Dx(i) (table[(i)].second.second->first) 00533 00534 // calculate slopes at points i and i+1: 00535 Y_type yp1; 00536 Y_type & yp2 = r; // alias r with yp2; 00537 if (i == 0) { // i is left endpoint 00538 yp1 = lslope; 00539 } 00540 else { 00541 yp1 = Yp(i-1); yp1 *= Dx(i)/Dx(i-1); yp1 += Yp(i); 00542 yp1 *= Dx(i-1)/(Dx(i)+Dx(i-1)); 00543 } 00544 if (i == table.size()-2) { // i+1 is right endpoint 00545 yp2 = rslope; 00546 } 00547 else { 00548 yp2 = Yp(i+1); yp2 *= Dx(i)/Dx(i+1); yp2 += Yp(i); 00549 yp2 *= Dx(i+1)/(Dx(i)+Dx(i+1)); 00550 } 00551 00552 // now do a linear interpolation between yp1 and yp2: 00553 double A = (x-table[i].first)/Dx(i); 00554 yp2 -= yp1; yp2 *= A; yp2 += yp1; // yp2 is the result 00555 00556 #undef Y 00557 #undef Yp 00558 #undef Dx 00559 } 00560 00561 00562 template < class Y_type > inline 00563 void interpolator<Y_type>::prime_spline 00564 (interpolator<Y_type>::index i, double x, Y_type & r) const 00565 { 00566 // convenient readablility macros: 00567 #define Y(i) (table[(i)].second.first->second) 00568 #define Yp(i) (table[(i)].second.second->second) 00569 #define Dx(i) (table[(i)].second.second->first) 00570 00571 Y_type yp(Y(i+1)); yp -= Y(i); yp *= 1.0/Dx(i); // the average slope from i to i+1 00572 double B = (x-table[i].first)/Dx(i), A = 1.0-B; // B == (x-x[i])/(x[i+1]-x[i]) 00573 00574 // using the yp, A and B defined above, the formula for Y'(x) is: 00575 // Y'(x) = yp - (3 A^2 - 1)/6 Dx(i) Y''(i) + (3 B^2 - 1)/6 Dx(i) Y''(i+1) 00576 00577 A = (3.0*A*A-1.0)*Dx(i)/6.0; B = (3.0*B*B-1.0)*Dx(i)/6.0; 00578 00579 r = Yp(i+1); r *= B/A; r -= Yp(i); r *= A; 00580 r += yp; 00581 00582 #undef Y 00583 #undef Yp 00584 #undef Dx 00585 } 00586 00587 00588 template < class Y_type > inline 00589 int interpolator<Y_type>::val_prime 00590 (double x, Y_type & y, Y_type & y_prime) const 00591 { 00592 if (!ready_) 00593 error::fatal("Must build interpolator before use."); 00594 int flag = 0; // will hold the returned extrapolation flag value 00595 00596 // attempt to find where in table to interpolate: 00597 const const_table_iter j = lower_bound(table.begin(), table.end(), x); // table[j] >= x; 00598 00599 // check if an extrapolation, else perform the interpolation 00600 if (j == table.begin()) { 00601 lextrapolate(x,y); 00602 y_prime = lslope; // linear extrapolation has a constant slope 00603 if ( x < j->first) { 00604 flag = -1; 00605 if (!no_warn_) 00606 error::warning("Interpolator extrapolating beyond range of data points."); 00607 } 00608 } 00609 else if (j == table.end()) { 00610 rextrapolate(x,y); 00611 y_prime = rslope; 00612 flag = 1; 00613 if (!no_warn_) 00614 error::warning("Interpolator extrapolating beyond range of data points."); 00615 } 00616 else { 00617 index i = (j - table.begin()) - 1; // now i is such that: x[i] < x <= x[i+1] 00618 switch (type_) { 00619 case LINEAR: { linear(i,x,y); prime_linear(i,x,y_prime); break; } 00620 case SPLINE: { spline(i,x,y); prime_spline(i,x,y_prime); break; } 00621 default: 00622 { error::fatal("Unknown interpolation type in interpolator."); } 00623 } 00624 } 00625 return flag; 00626 } 00627 00628 00629 // ******************************************************************** 00630 // debug functions for interpolator class 00631 00632 template < class Y_type > inline 00633 void interpolator<Y_type>::list_data_list() const 00634 { 00635 for (interpolator::const_data_iter i = data.begin(); i != data.end(); ++i) 00636 cout << i->first <<" , " << i->second << endl; 00637 } 00638 00639 template < class Y_type > inline 00640 void interpolator<Y_type>::list_lists() const 00641 { 00642 for (unsigned i = 0; i < table.size(); ++i) { 00643 const entry & t = table[i]; 00644 cout << t.first 00645 << "\t|\t" << t.second.first->first << " , " << t.second.first->second 00646 << "\t|\t" << t.second.second->first << " , " << t.second.second->second 00647 << endl; 00648 } 00649 } 00650 00651 // end num_interpolate.h
Please direct comments and corrections to
supermix@submm.caltech.edu
Go to the supermix home page
Generated by
1.2.7