1 // This code has been mechanically translated from the original FORTRAN 2 // code at http://netlib.org/quadpack. 3 4 /** Authors: Lars Tandle Kyllingstad 5 Copyright: Copyright (c) 2009, Lars T. Kyllingstad. All rights reserved. 6 License: Boost License 1.0 7 */ 8 module scid.ports.quadpack.qagse; 9 10 11 import std.algorithm: min, max; 12 import std.math: fabs; 13 14 import scid.ports.quadpack.qelg; 15 import scid.ports.quadpack.qk21; 16 import scid.ports.quadpack.qpsrt; 17 18 import scid.core.fortran; 19 20 21 22 23 /// 24 void qagse(Real, Func)(Func f, Real a, Real b, Real epsabs, Real epsrel, 25 int limit, out Real result, out Real abserr, out int neval, out int ier, 26 Real* alist_, Real* blist_, Real* rlist_, Real* elist_, int* iord_, 27 out int last) 28 { 29 //***begin prologue dqagse 30 //***date written 800101 (yymmdd) 31 //***revision date 830518 (yymmdd) 32 //***category no. h2a1a1 33 //***keywords automatic integrator, general-purpose, 34 // (end point) singularities, extrapolation, 35 // globally adaptive 36 //***author piessens,robert,appl. math. & progr. div. - k.u.leuven 37 // de doncker,elise,appl. math. & progr. div. - k.u.leuven 38 //***purpose the routine calculates an approximation result to a given 39 // definite integral i = integral of f over (a,b), 40 // hopefully satisfying following claim for accuracy 41 // abs(i-result).le.max(epsabs,epsrel*abs(i)). 42 //***description 43 // 44 // computation of a definite integral 45 // standard fortran subroutine 46 // double precision version 47 // 48 // parameters 49 // on entry 50 // f - double precision 51 // function subprogram defining the integrand 52 // function f(x). the actual name for f needs to be 53 // declared e x t e r n a l in the driver program. 54 // 55 // a - double precision 56 // lower limit of integration 57 // 58 // b - double precision 59 // upper limit of integration 60 // 61 // epsabs - double precision 62 // absolute accuracy requested 63 // epsrel - double precision 64 // relative accuracy requested 65 // if epsabs.le.0 66 // and epsrel.lt.max(50*rel.mach.acc.,0.5d-28), 67 // the routine will end with ier = 6. 68 // 69 // limit - integer 70 // gives an upperbound on the number of subintervals 71 // in the partition of (a,b) 72 // 73 // on return 74 // result - double precision 75 // approximation to the integral 76 // 77 // abserr - double precision 78 // estimate of the modulus of the absolute error, 79 // which should equal or exceed abs(i-result) 80 // 81 // neval - integer 82 // number of integrand evaluations 83 // 84 // ier - integer 85 // ier = 0 normal and reliable termination of the 86 // routine. it is assumed that the requested 87 // accuracy has been achieved. 88 // ier.gt.0 abnormal termination of the routine 89 // the estimates for integral and error are 90 // less reliable. it is assumed that the 91 // requested accuracy has not been achieved. 92 // error messages 93 // = 1 maximum number of subdivisions allowed 94 // has been achieved. one can allow more sub- 95 // divisions by increasing the value of limit 96 // (and taking the according dimension 97 // adjustments into account). however, if 98 // this yields no improvement it is advised 99 // to analyze the integrand in order to 100 // determine the integration difficulties. if 101 // the position of a local difficulty can be 102 // determined (e.g. singularity, 103 // discontinuity within the interval) one 104 // will probably gain from splitting up the 105 // interval at this point and calling the 106 // integrator on the subranges. if possible, 107 // an appropriate special-purpose integrator 108 // should be used, which is designed for 109 // handling the type of difficulty involved. 110 // = 2 the occurrence of roundoff error is detec- 111 // ted, which prevents the requested 112 // tolerance from being achieved. 113 // the error may be under-estimated. 114 // = 3 extremely bad integrand behaviour 115 // occurs at some points of the integration 116 // interval. 117 // = 4 the algorithm does not converge. 118 // roundoff error is detected in the 119 // extrapolation table. 120 // it is presumed that the requested 121 // tolerance cannot be achieved, and that the 122 // returned result is the best which can be 123 // obtained. 124 // = 5 the integral is probably divergent, or 125 // slowly convergent. it must be noted that 126 // divergence can occur with any other value 127 // of ier. 128 // = 6 the input is invalid, because 129 // epsabs.le.0 and 130 // epsrel.lt.max(50*rel.mach.acc.,0.5d-28). 131 // result, abserr, neval, last, rlist(1), 132 // iord(1) and elist(1) are set to zero. 133 // alist(1) and blist(1) are set to a and b 134 // respectively. 135 // 136 // alist - double precision 137 // vector of dimension at least limit, the first 138 // last elements of which are the left end points 139 // of the subintervals in the partition of the 140 // given integration range (a,b) 141 // 142 // blist - double precision 143 // vector of dimension at least limit, the first 144 // last elements of which are the right end points 145 // of the subintervals in the partition of the given 146 // integration range (a,b) 147 // 148 // rlist - double precision 149 // vector of dimension at least limit, the first 150 // last elements of which are the integral 151 // approximations on the subintervals 152 // 153 // elist - double precision 154 // vector of dimension at least limit, the first 155 // last elements of which are the moduli of the 156 // absolute error estimates on the subintervals 157 // 158 // iord - integer 159 // vector of dimension at least limit, the first k 160 // elements of which are pointers to the 161 // error estimates over the subintervals, 162 // such that elist(iord(1)), ..., elist(iord(k)) 163 // form a decreasing sequence, with k = last 164 // if last.le.(limit/2+2), and k = limit+1-last 165 // otherwise 166 // 167 // last - integer 168 // number of subintervals actually produced in the 169 // subdivision process 170 // 171 //***references (none) 172 //***routines called d1mach,dqelg,dqk21,dqpsrt 173 //***end prologue dqagse 174 // 175 Real abseps,area,area1,area12,area2,a1, 176 a2,b1,b2,correc,defabs,defab1,defab2, 177 dres,epmach,erlarg,erlast,errbnd,errmax, 178 error1,error2,erro12,errsum,ertest,oflow,resabs,reseps, 179 small,uflow; 180 Real[3] res3la_; 181 Real[52] rlist2_; 182 int id=1,ierro=1,iroff1=1,iroff2=1,iroff3=1,jupbnd=1,k=1,ksgn=1, 183 ktmin=1,maxerr=1,nres=1,nrmax=1,numrl2=1; 184 bool extrap,noext; 185 // 186 auto alist = dimension(alist_, limit); 187 auto blist = dimension(blist_, limit); 188 auto elist = dimension(elist_, limit); 189 auto iord = dimension(iord_, limit); 190 auto res3la = dimension(res3la_.ptr, limit); 191 auto rlist = dimension(rlist_, limit); 192 auto rlist2 = dimension(rlist2_.ptr, limit); 193 // 194 // the dimension of rlist2 is determined by the value of 195 // limexp in subroutine dqelg (rlist2 should be of dimension 196 // (limexp+2) at least). 197 // 198 // list of major variables 199 // ----------------------- 200 // 201 // alist - list of left end points of all subintervals 202 // considered up to now 203 // blist - list of right end points of all subintervals 204 // considered up to now 205 // rlist(i) - approximation to the integral over 206 // (alist(i),blist(i)) 207 // rlist2 - array of dimension at least limexp+2 containing 208 // the part of the epsilon table which is still 209 // needed for further computations 210 // elist(i) - error estimate applying to rlist(i) 211 // maxerr - pointer to the interval with largest error 212 // estimate 213 // errmax - elist(maxerr) 214 // erlast - error on the interval currently subdivided 215 // (before that subdivision has taken place) 216 // area - sum of the integrals over the subintervals 217 // errsum - sum of the errors over the subintervals 218 // errbnd - requested accuracy max(epsabs,epsrel* 219 // abs(result)) 220 // *****1 - variable for the left interval 221 // *****2 - variable for the right interval 222 // last - index for subdivision 223 // nres - number of calls to the extrapolation routine 224 // numrl2 - number of elements currently in rlist2. if an 225 // appropriate approximation to the compounded 226 // integral has been obtained it is put in 227 // rlist2(numrl2) after numrl2 has been increased 228 // by one. 229 // small - length of the smallest interval considered up 230 // to now, multiplied by 1.5 231 // erlarg - sum of the errors over the intervals larger 232 // than the smallest interval considered up to now 233 // extrap - logical variable denoting that the routine is 234 // attempting to perform extrapolation i.e. before 235 // subdividing the smallest interval we try to 236 // decrease the value of erlarg. 237 // noext - logical variable denoting that extrapolation 238 // is no longer allowed (true value) 239 // 240 // machine dependent constants 241 // --------------------------- 242 // 243 // epmach is the largest relative spacing. 244 // uflow is the smallest positive magnitude. 245 // oflow is the largest positive magnitude. 246 // 247 //***first executable statement dqagse 248 epmach = Real.epsilon; 249 // 250 // test on validity of parameters 251 // ------------------------------ 252 ier = 0; 253 neval = 0; 254 last = 0; 255 result = 0.0; 256 abserr = 0.0; 257 alist[1] = a; 258 blist[1] = b; 259 rlist[1] = 0.0; 260 elist[1] = 0.0; 261 if(epsabs <= 0.0 && epsrel < max(0.5e2*epmach,0.5e-28)) 262 ier = 6; 263 if(ier == 6) goto l999; 264 // 265 // first approximation to the integral 266 // ----------------------------------- 267 // 268 uflow = Real.min_normal; 269 oflow = Real.max; 270 ierro = 0; 271 qk21!(Real, typeof(f))(f,a,b,result,abserr,defabs,resabs); 272 // 273 // test on accuracy. 274 // 275 dres = fabs(result); 276 errbnd = max(epsabs,epsrel*dres); 277 last = 1; 278 rlist[1] = result; 279 elist[1] = abserr; 280 iord[1] = 1; 281 if(abserr <= 1.0e2*epmach*defabs && abserr > errbnd) ier = 2; 282 if(limit == 1) ier = 1; 283 if(ier != 0 || (abserr <= errbnd && abserr != resabs) || 284 abserr == 0.0) goto l140; 285 // 286 // initialization 287 // -------------- 288 // 289 rlist2[1] = result; 290 errmax = abserr; 291 maxerr = 1; 292 area = result; 293 errsum = abserr; 294 abserr = oflow; 295 nrmax = 1; 296 nres = 0; 297 numrl2 = 2; 298 ktmin = 0; 299 extrap = false; 300 noext = false; 301 iroff1 = 0; 302 iroff2 = 0; 303 iroff3 = 0; 304 ksgn = -1; 305 if(dres >= (0.1e1-0.5e2*epmach)*defabs) ksgn = 1; 306 // 307 // main do-loop 308 // ------------ 309 // 310 for (last=2; last<=limit; last++) { //do 90 last = 2,limit 311 // 312 // bisect the subinterval with the nrmax-th largest error 313 // estimate. 314 // 315 a1 = alist[maxerr]; 316 b1 = 0.5*(alist[maxerr]+blist[maxerr]); 317 a2 = b1; 318 b2 = blist[maxerr]; 319 erlast = errmax; 320 qk21!(Real, typeof(f))(f,a1,b1,area1,error1,resabs,defab1); 321 qk21!(Real, typeof(f))(f,a2,b2,area2,error2,resabs,defab2); 322 // 323 // improve previous approximations to integral 324 // and error and test for accuracy. 325 // 326 area12 = area1+area2; 327 erro12 = error1+error2; 328 errsum = errsum+erro12-errmax; 329 area = area+area12-rlist[maxerr]; 330 if(defab1 == error1 || defab2 == error2) goto l15; 331 if(fabs(rlist[maxerr]-area12) > 0.1e-4*fabs(area12) 332 || erro12 < 0.99*errmax) goto l10; 333 if(extrap) iroff2 = iroff2+1; 334 if(!extrap) iroff1 = iroff1+1; 335 l10: if(last > 10 && erro12 > errmax) iroff3 = iroff3+1; 336 l15: rlist[maxerr] = area1; 337 rlist[last] = area2; 338 errbnd = max(epsabs,epsrel*fabs(area)); 339 // 340 // test for roundoff error and eventually set error flag. 341 // 342 if(iroff1+iroff2 >= 10 || iroff3 >= 20) ier = 2; 343 if(iroff2 >= 5) ierro = 3; 344 // 345 // set error flag in the case that the number of subintervals 346 // equals limit. 347 // 348 if(last == limit) ier = 1; 349 // 350 // set error flag in the case of bad integrand behaviour 351 // at a point of the integration range. 352 // 353 if(max(fabs(a1),fabs(b2)) <= (0.1e1+0.1e3*epmach)* 354 (fabs(a2)+0.1e4*uflow)) ier = 4; 355 // 356 // append the newly-created intervals to the list. 357 // 358 if(error2 > error1) goto l20; 359 alist[last] = a2; 360 blist[maxerr] = b1; 361 blist[last] = b2; 362 elist[maxerr] = error1; 363 elist[last] = error2; 364 goto l30; 365 l20: alist[maxerr] = a2; 366 alist[last] = a1; 367 blist[last] = b1; 368 rlist[maxerr] = area2; 369 rlist[last] = area1; 370 elist[maxerr] = error2; 371 elist[last] = error1; 372 // 373 // call subroutine dqpsrt to maintain the descending ordering 374 // in the list of error estimates and select the subinterval 375 // with nrmax-th largest error estimate (to be bisected next). 376 // 377 l30: qpsrt!Real(limit,last,maxerr,errmax,elist.ptr,iord.ptr,nrmax); 378 // ***jump out of do-loop 379 if(errsum <= errbnd) goto l115; 380 // ***jump out of do-loop 381 if(ier != 0) goto l100; 382 if(last == 2) goto l80; 383 if(noext) goto l90; 384 erlarg = erlarg-erlast; 385 if(fabs(b1-a1) > small) erlarg = erlarg+erro12; 386 if(extrap) goto l40; 387 // 388 // test whether the interval to be bisected next is the 389 // smallest interval. 390 // 391 if(fabs(blist[maxerr]-alist[maxerr]) > small) goto l90; 392 extrap = true; 393 nrmax = 2; 394 l40: if(ierro == 3 || erlarg <= ertest) goto l60; 395 // 396 // the smallest interval has the largest error. 397 // before bisecting decrease the sum of the errors over the 398 // larger intervals (erlarg) and perform extrapolation. 399 // 400 id = nrmax; 401 jupbnd = last; 402 if(last > (2+limit/2)) jupbnd = limit+3-last; 403 for (k=id; k<=jupbnd; k++) { //do 50 k = id,jupbnd 404 maxerr = iord[nrmax]; 405 errmax = elist[maxerr]; 406 // ***jump out of do-loop 407 if(fabs(blist[maxerr]-alist[maxerr]) > small) goto l90; 408 nrmax = nrmax+1; 409 l50:; } 410 // 411 // perform extrapolation. 412 // 413 l60: numrl2 = numrl2+1; 414 rlist2[numrl2] = area; 415 qelg!Real(numrl2,rlist2.ptr,reseps,abseps,res3la.ptr,nres); 416 ktmin = ktmin+1; 417 if(ktmin > 5 && abserr < 0.1e-2*errsum) ier = 5; 418 if(abseps >= abserr) goto l70; 419 ktmin = 0; 420 abserr = abseps; 421 result = reseps; 422 correc = erlarg; 423 ertest = max(epsabs,epsrel*fabs(reseps)); 424 // ***jump out of do-loop 425 if(abserr <= ertest) goto l100; 426 // 427 // prepare bisection of the smallest interval. 428 // 429 l70: if(numrl2 == 1) noext = true; 430 if(ier == 5) goto l100; 431 maxerr = iord[1]; 432 errmax = elist[maxerr]; 433 nrmax = 1; 434 extrap = false; 435 small = small*0.5; 436 erlarg = errsum; 437 goto l90; 438 l80: small = fabs(b-a)*0.375; 439 erlarg = errsum; 440 ertest = errbnd; 441 rlist2[2] = area; 442 l90:;} 443 // 444 // set final result and error estimate. 445 // ------------------------------------ 446 // 447 l100: if(abserr == oflow) goto l115; 448 if(ier+ierro == 0) goto l110; 449 if(ierro == 3) abserr = abserr+correc; 450 if(ier == 0) ier = 3; 451 if(result != 0.0 && area != 0.0) goto l105; 452 if(abserr > errsum) goto l115; 453 if(area == 0.0) goto l130; 454 goto l110; 455 l105: if(abserr/fabs(result) > errsum/fabs(area)) goto l115; 456 // 457 // test on divergence. 458 // 459 l110: if(ksgn == (-1) && max(fabs(result),fabs(area)) <= 460 defabs*0.1e-1) goto l130; 461 if(0.1e-1 > (result/area) || (result/area) > 0.1e3 462 || errsum > fabs(area)) ier = 6; 463 goto l130; 464 // 465 // compute global integral sum. 466 // 467 l115: result = 0.0; 468 for (k=1; k<=last; k++) { //do 120 k = 1,last 469 result = result+rlist[k]; 470 l120: ;} 471 abserr = errsum; 472 l130: if(ier > 2) ier = ier-1; 473 l140: neval = 42*last-21; 474 l999: return; 475 } 476 477 unittest 478 { 479 alias qagse!(float, float delegate(float)) fqagse; 480 alias qagse!(double, double delegate(double)) dqagse; 481 alias qagse!(double, double function(double)) dfqagse; 482 alias qagse!(real, real delegate(real)) rqagse; 483 }