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