1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
C/MEMBR ADD NAME=EPSALG,SSI=0
subroutine epsalg(n, epstab, result, abserr, res3la, nres)
c
c based on quadpack routine epsalg
c ******************************************************
c
c purpose
c the routine transforms a given sequence of
c approximations, by means of the epsilon
c algorithm of p. wynn.
c
c an estimate of the absolute error is also given.
c the condensed epsilon table is computed. only those
c elements needed for the computation of the
c next diagonal are preserved.
c
c calling sequence
c call epsalg (n,epstab,result,abserr,res3la,nres)
c
c parameters
c n - epstab(n) contains the new element in the
c first column of the epsilon table.
c
c epstab - one dimensional array containing the
c elements of the two lower diagonals of
c the triangular epsilon table.
c the elements are numbered starting at the
c right-hand corner of the triangle.
c the dimension should be at least n+2.
c
c result - resulting approximation to the integral
c
c abserr - estimate of the absolute error computed from
c result and the 3 previous /results/
c
c res3la - array containing the last 3 /results/
c
c nres - number of calls to the routine
c (should be zero at first call)
c
c ******************************************************
c .. scalar arguments ..
double precision abserr, result
integer n, nres
c .. array arguments ..
double precision epstab(52), res3la(3)
c ..
c .. local scalars ..
double precision delta1, delta2, delta3, e0, e1, e1abs, e2, e3,
* epmach,epsinf, err1, err2, err3, error, oflow, res, ss, tol1,
* tol2,tol3
integer i, ib2, ib, ie, ind, k1, k2, k3, limexp, newelm, num
c .. function references ..
double precision dlamch
c ..
c
c machine dependent constants
c -------------------------
c /limexp/ is the maximum number of elements the epsilon
c table can contain. if this number is reached, the upper
c diagonal of the epsilon table is deleted.
c
data limexp /50/
epmach=dlamch('p')
oflow=dlamch('o')
c
c list of major variables
c -----------------------
c e0 - the 4 elements on which the
c e1 computation of a new element in
c e2 the epsilon table is based
c e3 e0
c e3 e1 new
c e2
c newelm - number of elements to be computed in the new
c diagonal
c error - error = abs(e1-e0)+abs(e2-e1)+abs(new-e2)
c result - the element in the new diagonal with least
c error
c
nres = nres + 1
abserr = oflow
result = epstab(n)
if (n.lt.3) go to 200
epstab(n+2) = epstab(n)
newelm = (n-1)/2
epstab(n) = oflow
num = n
k1 = n
do 80 i=1,newelm
k2 = k1 - 1
k3 = k1 - 2
res = epstab(k1+2)
e0 = epstab(k3)
e1 = epstab(k2)
e2 = res
e1abs = abs(e1)
delta2 = e2 - e1
err2 = abs(delta2)
tol2 = max(abs(e2),e1abs)*epmach
delta3 = e1 - e0
err3 = abs(delta3)
tol3 = max(e1abs,abs(e0))*epmach
if (err2.gt.tol2 .or. err3.gt.tol3) go to 20
c
c if e0, e1 and e2 are equal to within machine
c accuracy, convergence is assumed
c result = e2
c abserr = abs(e1-e0)+abs(e2-e1)
c
result = res
abserr = err2 + err3
go to 200
20 e3 = epstab(k1)
epstab(k1) = e1
delta1 = e1 - e3
err1 = abs(delta1)
tol1 = max(e1abs,abs(e3))*epmach
c
c if two elements are very close to each other, omit
c a part of the table by adjusting the value of n
c
if (err1.lt.tol1 .or. err2.lt.tol2 .or. err3.lt.tol3) goto 40
ss = 0.10d+01/delta1 + 0.10d+01/delta2 - 0.10d+01/delta3
epsinf = abs(ss*e1)
c
c test to detect irregular behaviour in the table, and
c eventually omit a part of the table adjusting the value
c of n
c
if (epsinf.gt.0.10d-03) go to 60
40 n = i + i - 1
go to 100
c
c compute a new element and eventually adjust
c the value of result
c
60 res = e1 + 0.10d+01/ss
epstab(k1) = res
k1 = k1 - 2
error = err2 + abs(res-e2) + err3
if (error.gt.abserr) go to 80
abserr = error
result = res
80 continue
c
c shift the table
c
100 if (n.eq.limexp) n = 2*(limexp/2) - 1
ib = 1
if ((num/2)*2.eq.num) ib = 2
ie = newelm + 1
do 120 i=1,ie
ib2 = ib + 2
epstab(ib) = epstab(ib2)
ib = ib2
120 continue
if (num.eq.n) go to 160
ind = num - n + 1
do 140 i=1,n
epstab(i) = epstab(ind)
ind = ind + 1
140 continue
160 if (nres.ge.4) go to 180
res3la(nres) = result
abserr = oflow
go to 200
c
c compute error estimate
c
180 abserr = abs(result-res3la(3)) + abs(result-res3la(2)) +
*abs(result-res3la(1))
res3la(1) = res3la(2)
res3la(2) = res3la(3)
res3la(3) = result
200 abserr = max(abserr,5.0d+00*epmach*abs(result))
return
end
|