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_GSL_INTE_QNG_H 00024 #define O2SCL_GSL_INTE_QNG_H 00025 00026 #include <o2scl/inte.h> 00027 #include <o2scl/gsl_inte.h> 00028 00029 /** \brief A namespace for the quadrature coefficients for 00030 non-adaptive integration 00031 00032 <b>Documentation from GSL</b>: \n 00033 Gauss-Kronrod-Patterson quadrature coefficients for use in 00034 quadpack routine qng. These coefficients were calculated with 00035 101 decimal digit arithmetic by L. W. Fullerton, Bell Labs, Nov 00036 1981. 00037 00038 */ 00039 namespace o2scl_inte_qng_coeffs { 00040 00041 /** Abscissae common to the 10-, 21-, 43- and 87-point rule */ 00042 static const double x1[5] = { 00043 0.973906528517171720077964012084452, 00044 0.865063366688984510732096688423493, 00045 0.679409568299024406234327365114874, 00046 0.433395394129247190799265943165784, 00047 0.148874338981631210884826001129720 00048 } ; 00049 00050 /** Weights of the 10-point formula */ 00051 static const double w10[5] = { 00052 0.066671344308688137593568809893332, 00053 0.149451349150580593145776339657697, 00054 0.219086362515982043995534934228163, 00055 0.269266719309996355091226921569469, 00056 0.295524224714752870173892994651338 00057 } ; 00058 00059 /** Abscissae common to the 21-, 43- and 87-point rule */ 00060 static const double x2[5] = { 00061 0.995657163025808080735527280689003, 00062 0.930157491355708226001207180059508, 00063 0.780817726586416897063717578345042, 00064 0.562757134668604683339000099272694, 00065 0.294392862701460198131126603103866 00066 } ; 00067 00068 /** Weights of the 21-point formula for abscissae x1 */ 00069 static const double w21a[5] = { 00070 0.032558162307964727478818972459390, 00071 0.075039674810919952767043140916190, 00072 0.109387158802297641899210590325805, 00073 0.134709217311473325928054001771707, 00074 0.147739104901338491374841515972068 00075 } ; 00076 00077 /** Weights of the 21-point formula for abscissae x2 */ 00078 static const double w21b[6] = { 00079 0.011694638867371874278064396062192, 00080 0.054755896574351996031381300244580, 00081 0.093125454583697605535065465083366, 00082 0.123491976262065851077958109831074, 00083 0.142775938577060080797094273138717, 00084 0.149445554002916905664936468389821 00085 } ; 00086 00087 /** Abscissae common to the 43- and 87-point rule */ 00088 static const double x3[11] = { 00089 0.999333360901932081394099323919911, 00090 0.987433402908088869795961478381209, 00091 0.954807934814266299257919200290473, 00092 0.900148695748328293625099494069092, 00093 0.825198314983114150847066732588520, 00094 0.732148388989304982612354848755461, 00095 0.622847970537725238641159120344323, 00096 0.499479574071056499952214885499755, 00097 0.364901661346580768043989548502644, 00098 0.222254919776601296498260928066212, 00099 0.074650617461383322043914435796506 00100 } ; 00101 00102 /** Weights of the 43-point formula for abscissae x1, x3 */ 00103 static const double w43a[10] = { 00104 0.016296734289666564924281974617663, 00105 0.037522876120869501461613795898115, 00106 0.054694902058255442147212685465005, 00107 0.067355414609478086075553166302174, 00108 0.073870199632393953432140695251367, 00109 0.005768556059769796184184327908655, 00110 0.027371890593248842081276069289151, 00111 0.046560826910428830743339154433824, 00112 0.061744995201442564496240336030883, 00113 0.071387267268693397768559114425516 00114 } ; 00115 00116 /** Weights of the 43-point formula for abscissae x3 */ 00117 static const double w43b[12] = { 00118 0.001844477640212414100389106552965, 00119 0.010798689585891651740465406741293, 00120 0.021895363867795428102523123075149, 00121 0.032597463975345689443882222526137, 00122 0.042163137935191811847627924327955, 00123 0.050741939600184577780189020092084, 00124 0.058379395542619248375475369330206, 00125 0.064746404951445885544689259517511, 00126 0.069566197912356484528633315038405, 00127 0.072824441471833208150939535192842, 00128 0.074507751014175118273571813842889, 00129 0.074722147517403005594425168280423 00130 } ; 00131 00132 /** Abscissae of the 87-point rule */ 00133 static const double x4[22] = { 00134 0.999902977262729234490529830591582, 00135 0.997989895986678745427496322365960, 00136 0.992175497860687222808523352251425, 00137 0.981358163572712773571916941623894, 00138 0.965057623858384619128284110607926, 00139 0.943167613133670596816416634507426, 00140 0.915806414685507209591826430720050, 00141 0.883221657771316501372117548744163, 00142 0.845710748462415666605902011504855, 00143 0.803557658035230982788739474980964, 00144 0.757005730685495558328942793432020, 00145 0.706273209787321819824094274740840, 00146 0.651589466501177922534422205016736, 00147 0.593223374057961088875273770349144, 00148 0.531493605970831932285268948562671, 00149 0.466763623042022844871966781659270, 00150 0.399424847859218804732101665817923, 00151 0.329874877106188288265053371824597, 00152 0.258503559202161551802280975429025, 00153 0.185695396568346652015917141167606, 00154 0.111842213179907468172398359241362, 00155 0.037352123394619870814998165437704 00156 } ; 00157 00158 /** Weights of the 87-point formula for abscissae x1, x2, x3 */ 00159 static const double w87a[21] = { 00160 0.008148377384149172900002878448190, 00161 0.018761438201562822243935059003794, 00162 0.027347451050052286161582829741283, 00163 0.033677707311637930046581056957588, 00164 0.036935099820427907614589586742499, 00165 0.002884872430211530501334156248695, 00166 0.013685946022712701888950035273128, 00167 0.023280413502888311123409291030404, 00168 0.030872497611713358675466394126442, 00169 0.035693633639418770719351355457044, 00170 0.000915283345202241360843392549948, 00171 0.005399280219300471367738743391053, 00172 0.010947679601118931134327826856808, 00173 0.016298731696787335262665703223280, 00174 0.021081568889203835112433060188190, 00175 0.025370969769253827243467999831710, 00176 0.029189697756475752501446154084920, 00177 0.032373202467202789685788194889595, 00178 0.034783098950365142750781997949596, 00179 0.036412220731351787562801163687577, 00180 0.037253875503047708539592001191226 00181 } ; 00182 00183 /** Weights of the 87-point formula for abscissae x4 */ 00184 static const double w87b[23] = { 00185 0.000274145563762072350016527092881, 00186 0.001807124155057942948341311753254, 00187 0.004096869282759164864458070683480, 00188 0.006758290051847378699816577897424, 00189 0.009549957672201646536053581325377, 00190 0.012329447652244853694626639963780, 00191 0.015010447346388952376697286041943, 00192 0.017548967986243191099665352925900, 00193 0.019938037786440888202278192730714, 00194 0.022194935961012286796332102959499, 00195 0.024339147126000805470360647041454, 00196 0.026374505414839207241503786552615, 00197 0.028286910788771200659968002987960, 00198 0.030052581128092695322521110347341, 00199 0.031646751371439929404586051078883, 00200 0.033050413419978503290785944862689, 00201 0.034255099704226061787082821046821, 00202 0.035262412660156681033782717998428, 00203 0.036076989622888701185500318003895, 00204 0.036698604498456094498018047441094, 00205 0.037120549269832576114119958413599, 00206 0.037334228751935040321235449094698, 00207 0.037361073762679023410321241766599 00208 } ; 00209 00210 } 00211 00212 #ifndef DOXYGENP 00213 namespace o2scl { 00214 #endif 00215 00216 /** 00217 \brief Non-adaptive integration from a to b (GSL) 00218 00219 integ() uses 10-point, 21-point, 43-point, and 87-point 00220 Gauss-Kronrod integration successively until the integral 00221 is returned within the accuracy specified by tolx and 00222 tolf. 00223 00224 \future Compare directly with GSL as is done in gsl_inte_qag_ts. 00225 */ 00226 template<class param_t, class func_t> class gsl_inte_qng : 00227 public inte<param_t,func_t>, public gsl_inte { 00228 00229 public: 00230 00231 /** 00232 \brief The number of function evalutions for the last integration 00233 00234 Set to either 0, 21, 43, or 87, depending on the number of 00235 function evaluations that were used. This variable is zero if 00236 an error occurs before any function evaluations were performed 00237 and is never equal 10, since in the 10-point method, the 00238 21-point result is used to estimate the error. If the function 00239 fails to achieve the desired precision, feval is set to 88. 00240 */ 00241 size_t feval; 00242 00243 /** \brief Integrate function \c func from \c a to \c b. 00244 */ 00245 virtual double integ(func_t &func, double a, double b, param_t &pa) { 00246 double res; 00247 integ_err(func,a,b,pa,res,this->interror); 00248 return res; 00249 } 00250 00251 /** \brief Integrate function \c func from \c a to \c b 00252 giving result \c res and error \c err 00253 */ 00254 virtual int integ_err(func_t &func, double a, double b, 00255 param_t &pa, double &res, double &err2) { 00256 00257 double fv1[5], fv2[5], fv3[5], fv4[5]; 00258 00259 /* array of function values which have been computed */ 00260 double savfun[21]; 00261 00262 /* 10, 21, 43 and 87 point results */ 00263 double res10, res21, res43, res87; 00264 00265 double result_kronrod, err; 00266 00267 /* approximation to the integral of abs(f) */ 00268 double resabs; 00269 00270 /* approximation to the integral of abs(f-i/(b-a)) */ 00271 double resasc; 00272 00273 const double half_length = 0.5 * (b - a); 00274 const double abs_half_length = fabs (half_length); 00275 const double center = 0.5 * (b + a); 00276 00277 double f_center; 00278 func(center,f_center,pa); 00279 00280 int k; 00281 00282 if (this->tolx <= 0 && (this->tolf < 50 * GSL_DBL_EPSILON || 00283 this->tolf < 0.5e-28)) { 00284 res = 0; 00285 err2 = 0; 00286 feval = 0; 00287 00288 std::string estr="Tolerance cannot be achieved with given "; 00289 estr+="value of 'tolx' and 'tolf' in gsl_inte_qng::integ_err()."; 00290 set_err_ret(estr.c_str(),gsl_ebadtol); 00291 }; 00292 00293 /* Compute the integral using the 10- and 21-point formula. */ 00294 00295 res10 = 0; 00296 res21 = o2scl_inte_qng_coeffs::w21b[5] * f_center; 00297 resabs = o2scl_inte_qng_coeffs::w21b[5] * fabs (f_center); 00298 00299 00300 for (k = 0; k < 5; k++) { 00301 const double abscissa = half_length * o2scl_inte_qng_coeffs::x1[k]; 00302 double fval1, fval2; 00303 func(center+abscissa,fval1,pa); 00304 func(center-abscissa,fval2,pa); 00305 const double fval = fval1 + fval2; 00306 res10 += o2scl_inte_qng_coeffs::w10[k] * fval; 00307 res21 += o2scl_inte_qng_coeffs::w21a[k] * fval; 00308 resabs += o2scl_inte_qng_coeffs::w21a[k] * 00309 (fabs (fval1) + fabs (fval2)); 00310 savfun[k] = fval; 00311 fv1[k] = fval1; 00312 fv2[k] = fval2; 00313 } 00314 00315 for (k = 0; k < 5; k++) { 00316 const double abscissa = half_length * o2scl_inte_qng_coeffs::x2[k]; 00317 double fval1, fval2; 00318 func(center+abscissa,fval1,pa); 00319 func(center-abscissa,fval2,pa); 00320 const double fval = fval1 + fval2; 00321 res21 += o2scl_inte_qng_coeffs::w21b[k] * fval; 00322 resabs += o2scl_inte_qng_coeffs::w21b[k] * 00323 (fabs (fval1) + fabs (fval2)); 00324 savfun[k + 5] = fval; 00325 fv3[k] = fval1; 00326 fv4[k] = fval2; 00327 } 00328 00329 resabs *= abs_half_length ; 00330 00331 { 00332 const double mean = 0.5 * res21; 00333 00334 resasc = o2scl_inte_qng_coeffs::w21b[5] * fabs (f_center - mean); 00335 00336 for (k = 0; k < 5; k++) { 00337 resasc += 00338 (o2scl_inte_qng_coeffs::w21a[k] * (fabs (fv1[k] - mean) + 00339 fabs (fv2[k] - mean)) 00340 + o2scl_inte_qng_coeffs::w21b[k] * (fabs (fv3[k] - mean) + 00341 fabs (fv4[k] - mean))); 00342 } 00343 resasc *= abs_half_length ; 00344 } 00345 00346 result_kronrod = res21 * half_length; 00347 00348 err = rescale_error ((res21 - res10) * half_length, resabs, resasc) ; 00349 00350 /* test for convergence. */ 00351 00352 if (err < this->tolx || err < this->tolf * fabs (result_kronrod)) { 00353 res = result_kronrod ; 00354 err2 = err ; 00355 feval = 21; 00356 return gsl_success; 00357 } 00358 00359 /* compute the integral using the 43-point formula. */ 00360 00361 res43 = o2scl_inte_qng_coeffs::w43b[11] * f_center; 00362 00363 for (k = 0; k < 10; k++) { 00364 res43 += savfun[k] * o2scl_inte_qng_coeffs::w43a[k]; 00365 } 00366 00367 for (k = 0; k < 11; k++) { 00368 const double abscissa = half_length * o2scl_inte_qng_coeffs::x3[k]; 00369 double fval1, fval2; 00370 func(center+abscissa,fval1,pa); 00371 func(center-abscissa,fval2,pa); 00372 const double fval = fval1+fval2; 00373 res43 += fval * o2scl_inte_qng_coeffs::w43b[k]; 00374 savfun[k + 10] = fval; 00375 } 00376 00377 /* test for convergence */ 00378 result_kronrod = res43 * half_length; 00379 err = rescale_error ((res43 - res21) * half_length, resabs, resasc); 00380 00381 if (err < this->tolx || err < this->tolf * fabs (result_kronrod)) { 00382 res = result_kronrod ; 00383 err2 = err ; 00384 feval = 43; 00385 return gsl_success; 00386 } 00387 00388 /* compute the integral using the 87-point formula. */ 00389 00390 res87 = o2scl_inte_qng_coeffs::w87b[22] * f_center; 00391 00392 for (k = 0; k < 21; k++) { 00393 res87 += savfun[k] * o2scl_inte_qng_coeffs::w87a[k]; 00394 } 00395 00396 for (k = 0; k < 22; k++) { 00397 const double abscissa = half_length * o2scl_inte_qng_coeffs::x4[k]; 00398 double fval1, fval2; 00399 func(center+abscissa,fval1,pa); 00400 func(center-abscissa,fval2,pa); 00401 res87 += o2scl_inte_qng_coeffs::w87b[k] * (fval1+fval2); 00402 } 00403 00404 /* test for convergence */ 00405 00406 result_kronrod = res87 * half_length ; 00407 00408 err = rescale_error ((res87 - res43) * half_length, resabs, resasc); 00409 00410 if (err < this->tolx || err < this->tolf * fabs (result_kronrod)) { 00411 res = result_kronrod ; 00412 err2 = err ; 00413 feval = 87; 00414 return gsl_success; 00415 } 00416 00417 /* failed to converge */ 00418 res = result_kronrod ; 00419 err2 = err ; 00420 feval = 88; 00421 00422 std::string estr="Failed to reach tolerance "; 00423 estr+="in gsl_inte_qng::integ_err()."; 00424 set_err_ret(estr.c_str(),gsl_etol); 00425 } 00426 00427 /// Return string denoting type ("gsl_inte_qng") 00428 const char *type() { return "gsl_inte_qng"; } 00429 00430 }; 00431 00432 #ifndef DOXYGENP 00433 } 00434 #endif 00435 00436 #endif
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