db1slr.f 7.41 KB
SUBROUTINE DB1SLR(X,NB,IZE,B,NCALC)
C THIS ROUTINE CALCULATES BESSEL FUNCTIONS I AND J OF REAL
C ARGUMENT AND INTEGER ORDER.
C
C
C EXPLANATION OF VARIABLES IN THE CALLING SEQUENCE
C
C X DOUBLE PRECISION REAL ARGUMENT FOR WHICH I*S OR J*S
C ARE TO BE CALCULATED. IF I*S ARE TO BE CALCULATED,
C ABS(X) MUST BE LESS THAN EXPARG (WHICH SEE BELOW).
C NB INTEGER TYPE. 1 + HIGHEST ORDER TO BE CALCULATED.
C IT MUST BE POSITIVE.
C IZE INTEGER TYPE. ZERO IF J*S ARE TO BE CALCULATED, 1
C IF I*S ARE TO BE CALCULATED.
C B DOUBLE PRECISION VECTOR OF LENGTH NB, NEED NOT BE
C INITIALIZED BY USER. IF THE ROUTINE TERMINATES
C NORMALLY (NCALC=NB), IT RETURNS J(OR I)-SUB-ZERO
C THROUGH J(OR I)-SUB-NB-MINUS-ONE OF X IN THIS
C VECTOR.
C NCALC INTEGER TYPE, NEED NOT BE INITIALIZED BY USER.
C BEFORE USING THE RESULTS, THE USER SHOULD CHECK THAT
C NCALC=NB, I.E. ALL ORDERS HAVE BEEN CALCULATED TO
C THE DESIRED ACCURACY. SEE ERROR RETURNS BELOW.
C
C
C EXPLANATION OF MACHINE-DEPENDENT CONSTANTS
C
C NSIG DECIMAL SIGNIFICANCE DESIRED. SHOULD BE SET TO
C IFIX(ALOG10(2)*NBIT+1), WHERE NBIT IS THE NUMBER OF
C BITS IN THE MANTISSA OF A DOUBLE PRECISION VARIABLE.
C SETTING NSIG LOWER WILL RESULT IN DECREASED ACCURACY
C WHILE SETTING NSIG HIGHER WILL INCREASE CPU TIME
C WITHOUT INCREASING ACCURACY. THE TRUNCATION ERROR
C IS LIMITED TO T=.5*10**-NSIG FOR J*S OF ORDER LESS
C THAN ARGUMENT, AND TO A RELATIVE ERROR OF T FOR
C I*S AND THE OTHER J*S.
C NTEN LARGEST INTEGER K SUCH THAT 10**K IS MACHINE-
C REPRESENTABLE IN DOUBLE PRECISION.
C LARGEX UPPER LIMIT ON THE MAGNITUDE OF X. BEAR IN MIND
C THAT IF ABS(X)=N, THEN AT LEAST N ITERATIONS OF THE
C BACKWARD RECURSION WILL BE EXECUTED.
C EXPARG LARGEST DOUBLE PRECISION ARGUMENT THAT THE LIBRARY
C DEXP ROUTINE CAN HANDLE.
C
C PORT NOTE, SEPTEMBER 8,1976 -
C THE LARGEX AND EXPARG TESTS ARE MADE IN THE OUTER ROUTINES -
C DBESRJ AND DBESRI, WHICH CALL DB1SLR.
C
C
C ERROR RETURNS
C
C PORT NOTE, SEPTEMBER 8, 1976 -
C THE NOTES BELOW ARE KEPT IN FOR THE RECORD, BUT, AS ABOVE,
C THE ACTUAL TESTS ARE NOW IN THE OUTER CALLING ROUTINES.
C
C LET G DENOTE EITHER I OR J.
C IN CASE OF AN ERROR, NCALC.NE.NB, AND NOT ALL G*S
C ARE CALCULATED TO THE DESIRED ACCURACY.
C IF NCALC.LT.0, AN ARGUMENT IS OUT OF RANGE. NB.LE.0
C OR IZE IS NEITHER 0 NOR 1 OR IZE=1 AND ABS(X).GE.EXPARG.
C IN THIS CASE, THE B-VECTOR IS NOT CALCULATED, AND NCALC
C IS SET TO MIN0(NB,0)-1 SO NCALC.NE.NB.
C NB.GT.NCALC.GT.0 WILL OCCUR IF NB.GT.MAGX AND ABS(G-
C SUB-NB-OF-X/G-SUB-MAGX+NP-OF-X).LT.10.**(NTEN/2), I.E. NB
C IS MUCH GREATER THAN MAGX. IN THIS CASE, B(N) IS CALCU-
C LATED TO THE DESIRED ACCURACY FOR N.LE.NCALC, BUT FOR
C NCALC.LT.N.LE.NB, PRECISION IS LOST. IF N.GT.NCALC AND
C ABS(B(NCALC)/B(N)).EQ.10**-K, THEN THE LAST K SIGNIFICANT
C FIGURES OF B(N) ARE ERRONEOUS. IF THE USER WISHES TO
C CALCULATE B(N) TO HIGHER ACCURACY, HE SHOULD USE AN
C ASYMPTOTIC FORMULA FOR LARGE ORDER.
C
DOUBLE PRECISION DLOG10, DSQRT, DEXP,
1 X,B,P,TEST,TEMPA,TEMPB,TEMPC,SIGN,SUM,TOVER,
2 PLAST,POLD,PSAVE,PSAVEL,D1MACH
DIMENSION B(NB)
DATA NSIG/0/, NTEN/0/
IF(NSIG .NE. 0) GO TO 1
NSIG = IFIX(-ALOG10(SNGL(D1MACH(3)))+1.)
NTEN = DLOG10(D1MACH(2))
1 TEMPA=DABS(X)
MAGX=IFIX(SNGL(TEMPA))
C
SIGN=DBLE(FLOAT(1-2*IZE))
NCALC=NB
C USE 2-TERM ASCENDING SERIES FOR SMALL X
IF(TEMPA**4.LT..1D0**NSIG) GO TO 30
C INITIALIZE THE CALCULATION OF P*S
NBMX=NB-MAGX
N=MAGX+1
PLAST=1.D0
P=DBLE(FLOAT(2*N))/TEMPA
C CALCULATE GENERAL SIGNIFICANCE TEST
TEST=2.D0*1.D1**NSIG
IF(IZE.EQ.1.AND.2*MAGX.GT.5*NSIG) TEST=DSQRT(TEST*P)
IF(IZE.EQ.1.AND.2*MAGX.LE.5*NSIG) TEST=TEST/1.585**MAGX
M=0
IF(NBMX.LT.3) GO TO 4
C CALCULATE P*S UNTIL N=NB-1. CHECK FOR POSSIBLE OVERFLOW.
TOVER=1.D1**(NTEN-NSIG)
NSTART=MAGX+2
NEND=NB-1
DO 3 N=NSTART,NEND
POLD=PLAST
PLAST=P
P=DBLE(FLOAT(2*N))*PLAST/TEMPA-SIGN*POLD
IF(P-TOVER) 3,3,5
3 CONTINUE
C CALCULATE SPECIAL SIGNIFICANCE TEST FOR NBMX.GT.2.
TEST=DMAX1(TEST,DSQRT(PLAST*1.D1**NSIG)*DSQRT(2.D0*P))
C CALCULATE P*S UNTIL SIGNIFICANCE TEST PASSES
4 N=N+1
POLD=PLAST
PLAST=P
P=DBLE(FLOAT(2*N))*PLAST/TEMPA-SIGN*POLD
IF(P.LT.TEST) GO TO 4
IF(IZE.EQ.1.OR.M.EQ.1) GO TO 12
C FOR J*S, A STRONG VARIANT OF THE TEST IS NECESSARY.
C CALCULATE IT, AND CALCULATE P*S UNTIL THIS TEST IS PASSED.
M=1
TEMPB=P/PLAST
TEMPC=DBLE(FLOAT(N+1))/TEMPA
IF(TEMPB+1.D0/TEMPB.GT.2.D0*TEMPC)TEMPB=TEMPC+DSQRT(TEMPC**2-1.D0)
TEST=TEST/DSQRT(TEMPB-1.D0/TEMPB)
IF(P-TEST) 4,12,12
C TO AVOID OVERFLOW, DIVIDE P*S BY TOVER. CALCULATE P*S
C UNTIL ABS(P).GT.1.
5 TOVER=1.D1**NTEN
P=P/TOVER
PLAST=PLAST/TOVER
PSAVE=P
PSAVEL=PLAST
NSTART=N+1
6 N=N+1
POLD=PLAST
PLAST=P
P=DBLE(FLOAT(2*N))*PLAST/TEMPA-SIGN*POLD
IF(P.LE.1.D0) GO TO 6
TEMPB=DBLE(FLOAT(2*N))/TEMPA
IF(IZE.EQ.1) GO TO 8
TEMPC=.5D0*TEMPB
TEMPB=PLAST/POLD
IF(TEMPB+1.D0/TEMPB.GT.2.D0*TEMPC)TEMPB=TEMPC+DSQRT(TEMPC**2-1.D0)
C CALCULATE BACKWARD TEST, AND FIND NCALC, THE HIGHEST N
C SUCH THAT THE TEST IS PASSED.
8 TEST=.5D0*POLD*PLAST*(1.D0-1.D0/TEMPB**2)/1.D1**NSIG
P=PLAST*TOVER
N=N-1
NEND=MIN0(NB,N)
DO 9 NCALC=NSTART,NEND
POLD=PSAVEL
PSAVEL=PSAVE
PSAVE=DBLE(FLOAT(2*N))*PSAVEL/TEMPA-SIGN*POLD
IF(PSAVE*PSAVEL-TEST) 9,9,10
9 CONTINUE
NCALC=NEND+1
10 NCALC=NCALC-1
C THE SUM B(1)+2B(3)+2B(5)... IS USED TO NORMALIZE. M, THE
C COEFFICIENT OF B(N), IS INITIALIZED TO 2 OR 0.
12 N=N+1
M=2*N-4*(N/2)
C INITIALIZE THE BACKWARD RECURSION AND THE NORMALIZATION
C SUM
TEMPB=0.D0
TEMPA=1.D0/P
SUM=DBLE(FLOAT(M))*TEMPA
NEND=N-NB
IF(NEND) 17,15,13
C RECUR BACKWARD VIA DIFFERENCE EQUATION, CALCULATING (BUT
C NOT STORING) B(N), UNTIL N=NB.
13 DO 14 L=1,NEND
N=N-1
TEMPC=TEMPB
TEMPB=TEMPA
TEMPA=(DBLE(FLOAT(2*N))*TEMPB)/X-SIGN*TEMPC
M=2-M
14 SUM=SUM+DBLE(FLOAT(M))*TEMPA
C STORE B(NB)
15 B(N)=TEMPA
IF(NB.GT.1) GO TO 16
C NB=1. SINCE 2*TEMPA WAS ADDED TO THE SUM, TEMPA MUST BE
C SUBTRACTED
SUM=SUM-TEMPA
GO TO 23
C CALCULATE AND STORE B(NB-1)
16 N=N-1
B(N) =(DBLE(FLOAT(2*N))*TEMPA)/X-SIGN*TEMPB
IF(N.EQ.1) GO TO 22
M=2-M
SUM=SUM+DBLE(FLOAT(M))*B(N)
GO TO 19
C N.LT.NB, SO STORE B(N) AND SET HIGHER ORDERS TO ZERO
17 B(N)=TEMPA
NEND=-NEND
DO 18 L=1,NEND
K=N+L
18 B(K)=0.D0
19 NEND=N-2
IF(NEND.EQ.0) GO TO 21
C CALCULATE VIA DIFFERENCE EQUATION AND STORE B(N),
C UNTIL N=2
DO 20 L=1,NEND
N=N-1
B(N)=(DBLE(FLOAT(2*N))*B(N+1))/X-SIGN*B(N+2)
M=2-M
20 SUM=SUM+DBLE(FLOAT(M))*B(N)
C CALCULATE B(1)
21 B(1)=2.D0*B(2)/X-SIGN*B(3)
22 SUM=SUM+B(1)
C NORMALIZE--IF IZE=1, DIVIDE SUM BY COSH(X). DIVIDE ALL
C B(N) BY SUM.
23 IF(IZE.EQ.0) GO TO 25
TEMPA=DEXP(DABS(X))
SUM=2.D0*SUM/(TEMPA+1.D0/TEMPA)
25 DO 26 N=1,NB
26 B(N)=B(N)/SUM
RETURN
C
C TWO-TERM ASCENDING SERIES FOR SMALL X
30 TEMPA=1.D0
TEMPB=-.25D0*X*X*SIGN
B(1)=1.D0+TEMPB
IF(NB.EQ.1) GO TO 32
DO 31 N=2,NB
TEMPA=TEMPA*X/DBLE(FLOAT(2*N-2))
31 B(N)=TEMPA*(1.D0+TEMPB/DBLE(FLOAT(N)))
32 RETURN
END