Compute an approximation for the incomplete or complete elliptic integral of the 3rd kind: where , , and , and at most one of them , and .
If or or , then the integral is COMPLETE.
The duplication theorem is iterated until the variables are nearly equal, and the function is then expanded in Taylor series to fifth order.
where: and: The sum of the third and fourth terms on the left side is .
Changes in the program may improve speed at the expense of robustness.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | x | nonnegative variable |
||
| real(kind=wp), | intent(in) | :: | y | nonnegative variable |
||
| real(kind=wp), | intent(in) | :: | z | nonnegative variable |
||
| real(kind=wp), | intent(in) | :: | p | positive variable |
||
| integer, | intent(out) | :: | ier | indicates normal or abnormal termination:
|
real(wp) function drj(x,y,z,p,ier)
implicit none
real(wp),intent(in) :: x !! nonnegative variable
real(wp),intent(in) :: y !! nonnegative variable
real(wp),intent(in) :: z !! nonnegative variable
real(wp),intent(in) :: p !! positive variable
integer,intent(out) :: ier !! indicates normal or abnormal termination:
!!
!! * `IER = 0`: Normal and reliable termination of the
!! routine. It is assumed that the requested
!! accuracy has been achieved.
!! * `IER = 1`: `min(x,y,z) < 0.0_wp`
!! * `IER = 2`: `min(x+y,x+z,y+z,p) < LOLIM`
!! * `IER = 3`: `max(x,y,z,p) > UPLIM`
character(len=16) xern3 , xern4 , xern5 , xern6 , xern7
real(wp) :: alfa , beta , ea , eb , ec , e2 , e3, epslon
real(wp) :: lamda , mu , pn , pndev
real(wp) :: power4 , sigma , s1 , s2 , s3 , xn , xndev
real(wp) :: xnroot , yn , yndev , ynroot , zn , zndev , znroot
real(wp),parameter :: errtol = (d1mach(3)/3.0_wp)**(1.0_wp/6.0_wp)
!! Determines the accuracy of the answer
!!
!! the value assigned by the routine will result
!! in solution precision within 1-2 decimals of
!! "machine precision".
!!
!! Relative error due to truncation of the series for DRJ
!! is less than `3 * ERRTOL ** 6 / (1 - ERRTOL) ** 3/2`.
!!
!! The accuracy of the computed approximation to the integral
!! can be controlled by choosing the value of ERRTOL.
!! Truncation of a Taylor series after terms of fifth order
!! introduces an error less than the amount shown in the
!! second column of the following table for each value of
!! ERRTOL in the first column. In addition to the truncation
!! error there will be round-off error, but in practice the
!! total error from both sources is usually less than the
!! amount given in the table.
!!
!! Sample choices:
!! (ERRTOL, Relative truncation error less than}
!! (1.0e-3, 4.0e-18),
!! (3.0e-3, 3.0e-15),
!! (1.0e-2, 4.0e-12),
!! (3.0e-2, 3.0e-9),
!! (1.0e-1, 4.0e-6)
!!
!! Decreasing ERRTOL by a factor of 10 yields six more
!! decimal digits of accuracy at the expense of one or
!! two more iterations of the duplication theorem.
! LOLIM and UPLIM determine the valid range of X, Y, Z, and P
real(wp),parameter :: lolim = (5.0_wp*d1mach(1))**(1.0_wp/3.0_wp)
!! not less than the cube root of the value
!! of LOLIM used in the routine for [[DRC]].
real(wp),parameter :: uplim = 0.30_wp*(d1mach(2)/5.0_wp)**(1.0_wp/3.0_wp)
!! not greater than 0.3 times the cube root of
!! the value of UPLIM used in the routine for [[DRC]].
real(wp),parameter :: c1 = 3.0_wp/14.0_wp
real(wp),parameter :: c2 = 1.0_wp/3.0_wp
real(wp),parameter :: c3 = 3.0_wp/22.0_wp
real(wp),parameter :: c4 = 3.0_wp/26.0_wp
!initialize:
drj = 0.0_wp
! check for errors:
if ( min(x,y,z)<0.0_wp ) then
ier = 1
write (xern3,'(1pe15.6)') x
write (xern4,'(1pe15.6)') y
write (xern5,'(1pe15.6)') z
write(error_unit,'(a)') 'drj: min(x,y,z)<0 where x = '// &
xern3//' y = '//xern4//' and z = '//xern5
return
endif
if ( max(x,y,z,p)>uplim ) then
ier = 3
write (xern3,'(1pe15.6)') x
write (xern4,'(1pe15.6)') y
write (xern5,'(1pe15.6)') z
write (xern6,'(1pe15.6)') p
write (xern7,'(1pe15.6)') uplim
write(error_unit,'(a)') 'drj: max(x,y,z,p)>uplim where x = '// &
xern3//' y = '//xern4//' z = '//xern5//' p = '// &
xern6//' and uplim = '//xern7
return
endif
if ( min(x+y,x+z,y+z,p)<lolim ) then
ier = 2
write (xern3,'(1pe15.6)') x
write (xern4,'(1pe15.6)') y
write (xern5,'(1pe15.6)') z
write (xern6,'(1pe15.6)') p
write (xern7,'(1pe15.6)') lolim
write(error_unit,'(a)') 'drj: min(x+y,x+z,y+z,p)<lolim where x = '//xern3// &
' y = '//xern4//' z = '//xern5//' p = '//xern6// &
' and lolim = '//xern7
return
endif
ier = 0
xn = x
yn = y
zn = z
pn = p
sigma = 0.0_wp
power4 = 1.0_wp
do
mu = (xn+yn+zn+pn+pn)*0.20_wp
xndev = (mu-xn)/mu
yndev = (mu-yn)/mu
zndev = (mu-zn)/mu
pndev = (mu-pn)/mu
epslon = max(abs(xndev),abs(yndev),abs(zndev),abs(pndev))
if ( epslon<errtol ) exit
xnroot = sqrt(xn)
ynroot = sqrt(yn)
znroot = sqrt(zn)
lamda = xnroot*(ynroot+znroot) + ynroot*znroot
alfa = pn*(xnroot+ynroot+znroot) + xnroot*ynroot*znroot
alfa = alfa*alfa
beta = pn*(pn+lamda)*(pn+lamda)
sigma = sigma + power4*drc(alfa,beta,ier)
power4 = power4*0.250_wp
xn = (xn+lamda)*0.250_wp
yn = (yn+lamda)*0.250_wp
zn = (zn+lamda)*0.250_wp
pn = (pn+lamda)*0.250_wp
end do
ea = xndev*(yndev+zndev) + yndev*zndev
eb = xndev*yndev*zndev
ec = pndev*pndev
e2 = ea - 3.0_wp*ec
e3 = eb + 2.0_wp*pndev*(ea-ec)
s1 = 1.0_wp + e2*(-c1+0.750_wp*c3*e2-1.50_wp*c4*e3)
s2 = eb*(0.50_wp*c2+pndev*(-c3-c3+pndev*c4))
s3 = pndev*ea*(c2-pndev*c3) - c2*pndev*ec
drj = 3.0_wp*sigma + power4*(s1+s2+s3)/(mu*sqrt(mu))
end function drj