00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 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 /** x1, 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 /** w10, 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 /** x2, 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 /** w21a, 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 /** w21b, 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 /** x3, 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 /** w43a, 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 /** w43b, 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 /** x4, 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 /** w87a, 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 /** w87b, 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 template<class param_t, class func_t> class gsl_inte_qng : 00225 public inte<param_t,func_t>, public gsl_inte { 00226 00227 public: 00228 00229 /** 00230 \brief The number of function evalutions for the last integration 00231 00232 Set to either 0, 21, 43, or 87, depending on the number of 00233 function evaluations that were used. This variable is zero if 00234 an error occurs before any function evaluations were performed 00235 and is never equal 10, since in the 10-point method, the 00236 21-point result is used to estimate the error. If the function 00237 fails to achieve the desired precision, feval is set to 88. 00238 */ 00239 size_t feval; 00240 00241 /** \brief Integrate function \c func from \c a to \c b. 00242 */ 00243 virtual double integ(func_t &func, double a, double b, param_t &pa) { 00244 double res, err; 00245 integ_err(func,a,b,pa,res,err); 00246 this->interror=err; 00247 return res; 00248 } 00249 00250 /** \brief Integrate function \c func from \c a to \c b 00251 giving result \c res and error \c err 00252 */ 00253 virtual int integ_err(func_t &func, double a, double b, 00254 param_t &pa, double &res, double &err2) { 00255 00256 double fv1[5], fv2[5], fv3[5], fv4[5]; 00257 00258 /* array of function values which have been computed */ 00259 double savfun[21]; 00260 00261 /* 10, 21, 43 and 87 point results */ 00262 double res10, res21, res43, res87; 00263 00264 double result_kronrod, err; 00265 00266 /* approximation to the integral of abs(f) */ 00267 double resabs; 00268 00269 /* approximation to the integral of abs(f-i/(b-a)) */ 00270 double resasc; 00271 00272 const double half_length = 0.5 * (b - a); 00273 const double abs_half_length = fabs (half_length); 00274 const double center = 0.5 * (b + a); 00275 00276 double f_center; 00277 func(center,f_center,pa); 00278 00279 int k; 00280 00281 if (this->tolx <= 0 && (this->tolf < 50 * GSL_DBL_EPSILON || 00282 this->tolf < 0.5e-28)) { 00283 res = 0; 00284 err2 = 0; 00285 feval = 0; 00286 GSL_ERROR 00287 ("tolerance cannot be acheived with given tolx and tolf", 00288 GSL_EBADTOL); 00289 }; 00290 00291 /* Compute the integral using the 10- and 21-point formula. */ 00292 00293 res10 = 0; 00294 res21 = o2scl_inte_qng_coeffs::w21b[5] * f_center; 00295 resabs = o2scl_inte_qng_coeffs::w21b[5] * fabs (f_center); 00296 00297 00298 for (k = 0; k < 5; k++) { 00299 const double abscissa = half_length * o2scl_inte_qng_coeffs::x1[k]; 00300 double fval1, fval2; 00301 func(center+abscissa,fval1,pa); 00302 func(center-abscissa,fval2,pa); 00303 const double fval = fval1 + fval2; 00304 res10 += o2scl_inte_qng_coeffs::w10[k] * fval; 00305 res21 += o2scl_inte_qng_coeffs::w21a[k] * fval; 00306 resabs += o2scl_inte_qng_coeffs::w21a[k] * 00307 (fabs (fval1) + fabs (fval2)); 00308 savfun[k] = fval; 00309 fv1[k] = fval1; 00310 fv2[k] = fval2; 00311 } 00312 00313 for (k = 0; k < 5; k++) { 00314 const double abscissa = half_length * o2scl_inte_qng_coeffs::x2[k]; 00315 double fval1, fval2; 00316 func(center+abscissa,fval1,pa); 00317 func(center-abscissa,fval2,pa); 00318 const double fval = fval1 + fval2; 00319 res21 += o2scl_inte_qng_coeffs::w21b[k] * fval; 00320 resabs += o2scl_inte_qng_coeffs::w21b[k] * 00321 (fabs (fval1) + fabs (fval2)); 00322 savfun[k + 5] = fval; 00323 fv3[k] = fval1; 00324 fv4[k] = fval2; 00325 } 00326 00327 resabs *= abs_half_length ; 00328 00329 { 00330 const double mean = 0.5 * res21; 00331 00332 resasc = o2scl_inte_qng_coeffs::w21b[5] * fabs (f_center - mean); 00333 00334 for (k = 0; k < 5; k++) { 00335 resasc += 00336 (o2scl_inte_qng_coeffs::w21a[k] * (fabs (fv1[k] - mean) + 00337 fabs (fv2[k] - mean)) 00338 + o2scl_inte_qng_coeffs::w21b[k] * (fabs (fv3[k] - mean) + 00339 fabs (fv4[k] - mean))); 00340 } 00341 resasc *= abs_half_length ; 00342 } 00343 00344 result_kronrod = res21 * half_length; 00345 00346 err = rescale_error ((res21 - res10) * half_length, resabs, resasc) ; 00347 00348 /* test for convergence. */ 00349 00350 if (err < this->tolx || err < this->tolf * fabs (result_kronrod)) { 00351 res = result_kronrod ; 00352 err2 = err ; 00353 feval = 21; 00354 return gsl_success; 00355 } 00356 00357 /* compute the integral using the 43-point formula. */ 00358 00359 res43 = o2scl_inte_qng_coeffs::w43b[11] * f_center; 00360 00361 for (k = 0; k < 10; k++) { 00362 res43 += savfun[k] * o2scl_inte_qng_coeffs::w43a[k]; 00363 } 00364 00365 for (k = 0; k < 11; k++) { 00366 const double abscissa = half_length * o2scl_inte_qng_coeffs::x3[k]; 00367 double fval1, fval2; 00368 func(center+abscissa,fval1,pa); 00369 func(center-abscissa,fval2,pa); 00370 const double fval = fval1+fval2; 00371 res43 += fval * o2scl_inte_qng_coeffs::w43b[k]; 00372 savfun[k + 10] = fval; 00373 } 00374 00375 /* test for convergence */ 00376 result_kronrod = res43 * half_length; 00377 err = rescale_error ((res43 - res21) * half_length, resabs, resasc); 00378 00379 if (err < this->tolx || err < this->tolf * fabs (result_kronrod)) { 00380 res = result_kronrod ; 00381 err2 = err ; 00382 feval = 43; 00383 return gsl_success; 00384 } 00385 00386 /* compute the integral using the 87-point formula. */ 00387 00388 res87 = o2scl_inte_qng_coeffs::w87b[22] * f_center; 00389 00390 for (k = 0; k < 21; k++) { 00391 res87 += savfun[k] * o2scl_inte_qng_coeffs::w87a[k]; 00392 } 00393 00394 for (k = 0; k < 22; k++) { 00395 const double abscissa = half_length * o2scl_inte_qng_coeffs::x4[k]; 00396 double fval1, fval2; 00397 func(center+abscissa,fval1,pa); 00398 func(center-abscissa,fval2,pa); 00399 res87 += o2scl_inte_qng_coeffs::w87b[k] * (fval1+fval2); 00400 } 00401 00402 /* test for convergence */ 00403 00404 result_kronrod = res87 * half_length ; 00405 00406 err = rescale_error ((res87 - res43) * half_length, resabs, resasc); 00407 00408 if (err < this->tolx || err < this->tolf * fabs (result_kronrod)) { 00409 res = result_kronrod ; 00410 err2 = err ; 00411 feval = 87; 00412 return gsl_success; 00413 } 00414 00415 /* failed to converge */ 00416 res = result_kronrod ; 00417 err2 = err ; 00418 feval = 88; 00419 00420 GSL_ERROR("failed to reach tolerance with highest-order rule", 00421 GSL_ETOL) ; 00422 00423 } 00424 00425 /// Return string denoting type ("gsl_inte_qng") 00426 const char *type() { return "gsl_inte_qng"; } 00427 00428 }; 00429 00430 #ifndef DOXYGENP 00431 } 00432 #endif 00433 00434 #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