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 }