OpenLibm/slatec/dbesj.f
Viral B. Shah c977aa998f Add Makefile.extras to build libopenlibm-extras.
Replace amos with slatec
2012-12-31 16:37:05 -05:00

508 lines
14 KiB
Fortran

*DECK DBESJ
SUBROUTINE DBESJ (X, ALPHA, N, Y, NZ)
C***BEGIN PROLOGUE DBESJ
C***PURPOSE Compute an N member sequence of J Bessel functions
C J/SUB(ALPHA+K-1)/(X), K=1,...,N for non-negative ALPHA
C and X.
C***LIBRARY SLATEC
C***CATEGORY C10A3
C***TYPE DOUBLE PRECISION (BESJ-S, DBESJ-D)
C***KEYWORDS J BESSEL FUNCTION, SPECIAL FUNCTIONS
C***AUTHOR Amos, D. E., (SNLA)
C Daniel, S. L., (SNLA)
C Weston, M. K., (SNLA)
C***DESCRIPTION
C
C Abstract **** a double precision routine ****
C DBESJ computes an N member sequence of J Bessel functions
C J/sub(ALPHA+K-1)/(X), K=1,...,N for non-negative ALPHA and X.
C A combination of the power series, the asymptotic expansion
C for X to infinity and the uniform asymptotic expansion for
C NU to infinity are applied over subdivisions of the (NU,X)
C plane. For values of (NU,X) not covered by one of these
C formulae, the order is incremented or decremented by integer
C values into a region where one of the formulae apply. Backward
C recursion is applied to reduce orders by integer values except
C where the entire sequence lies in the oscillatory region. In
C this case forward recursion is stable and values from the
C asymptotic expansion for X to infinity start the recursion
C when it is efficient to do so. Leading terms of the series and
C uniform expansion are tested for underflow. If a sequence is
C requested and the last member would underflow, the result is
C set to zero and the next lower order tried, etc., until a
C member comes on scale or all members are set to zero.
C Overflow cannot occur.
C
C The maximum number of significant digits obtainable
C is the smaller of 14 and the number of digits carried in
C double precision arithmetic.
C
C Description of Arguments
C
C Input X,ALPHA are double precision
C X - X .GE. 0.0D0
C ALPHA - order of first member of the sequence,
C ALPHA .GE. 0.0D0
C N - number of members in the sequence, N .GE. 1
C
C Output Y is double precision
C Y - a vector whose first N components contain
C values for J/sub(ALPHA+K-1)/(X), K=1,...,N
C NZ - number of components of Y set to zero due to
C underflow,
C NZ=0 , normal return, computation completed
C NZ .NE. 0, last NZ components of Y set to zero,
C Y(K)=0.0D0, K=N-NZ+1,...,N.
C
C Error Conditions
C Improper input arguments - a fatal error
C Underflow - a non-fatal error (NZ .NE. 0)
C
C***REFERENCES D. E. Amos, S. L. Daniel and M. K. Weston, CDC 6600
C subroutines IBESS and JBESS for Bessel functions
C I(NU,X) and J(NU,X), X .GE. 0, NU .GE. 0, ACM
C Transactions on Mathematical Software 3, (1977),
C pp. 76-92.
C F. W. J. Olver, Tables of Bessel Functions of Moderate
C or Large Orders, NPL Mathematical Tables 6, Her
C Majesty's Stationery Office, London, 1962.
C***ROUTINES CALLED D1MACH, DASYJY, DJAIRY, DLNGAM, I1MACH, XERMSG
C***REVISION HISTORY (YYMMDD)
C 750101 DATE WRITTEN
C 890531 Changed all specific intrinsics to generic. (WRB)
C 890911 Removed unnecessary intrinsics. (WRB)
C 890911 REVISION DATE from Version 3.2
C 891214 Prologue converted to Version 4.0 format. (BAB)
C 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ)
C 900326 Removed duplicate information from DESCRIPTION section.
C (WRB)
C 920501 Reformatted the REFERENCES section. (WRB)
C***END PROLOGUE DBESJ
EXTERNAL DJAIRY
INTEGER I,IALP,IDALP,IFLW,IN,INLIM,IS,I1,I2,K,KK,KM,KT,N,NN,
1 NS,NZ
INTEGER I1MACH
DOUBLE PRECISION AK,AKM,ALPHA,ANS,AP,ARG,COEF,DALPHA,DFN,DTM,
1 EARG,ELIM1,ETX,FIDAL,FLGJY,FN,FNF,FNI,FNP1,FNU,
2 FNULIM,GLN,PDF,PIDT,PP,RDEN,RELB,RTTP,RTWO,RTX,RZDEN,
3 S,SA,SB,SXO2,S1,S2,T,TA,TAU,TB,TEMP,TFN,TM,TOL,
4 TOLLN,TRX,TX,T1,T2,WK,X,XO2,XO2L,Y,SLIM,RTOL
SAVE RTWO, PDF, RTTP, PIDT, PP, INLIM, FNULIM
DOUBLE PRECISION D1MACH, DLNGAM
DIMENSION Y(*), TEMP(3), FNULIM(2), PP(4), WK(7)
DATA RTWO,PDF,RTTP,PIDT / 1.34839972492648D+00,
1 7.85398163397448D-01, 7.97884560802865D-01, 1.57079632679490D+00/
DATA PP(1), PP(2), PP(3), PP(4) / 8.72909153935547D+00,
1 2.65693932265030D-01, 1.24578576865586D-01, 7.70133747430388D-04/
DATA INLIM / 150 /
DATA FNULIM(1), FNULIM(2) / 100.0D0, 60.0D0 /
C***FIRST EXECUTABLE STATEMENT DBESJ
NZ = 0
KT = 1
NS=0
C I1MACH(14) REPLACES I1MACH(11) IN A DOUBLE PRECISION CODE
C I1MACH(15) REPLACES I1MACH(12) IN A DOUBLE PRECISION CODE
TA = D1MACH(3)
TOL = MAX(TA,1.0D-15)
I1 = I1MACH(14) + 1
I2 = I1MACH(15)
TB = D1MACH(5)
ELIM1 = -2.303D0*(I2*TB+3.0D0)
RTOL=1.0D0/TOL
SLIM=D1MACH(1)*RTOL*1.0D+3
C TOLLN = -LN(TOL)
TOLLN = 2.303D0*TB*I1
TOLLN = MIN(TOLLN,34.5388D0)
IF (N-1) 720, 10, 20
10 KT = 2
20 NN = N
IF (X) 730, 30, 80
30 IF (ALPHA) 710, 40, 50
40 Y(1) = 1.0D0
IF (N.EQ.1) RETURN
I1 = 2
GO TO 60
50 I1 = 1
60 DO 70 I=I1,N
Y(I) = 0.0D0
70 CONTINUE
RETURN
80 CONTINUE
IF (ALPHA.LT.0.0D0) GO TO 710
C
IALP = INT(ALPHA)
FNI = IALP + N - 1
FNF = ALPHA - IALP
DFN = FNI + FNF
FNU = DFN
XO2 = X*0.5D0
SXO2 = XO2*XO2
C
C DECISION TREE FOR REGION WHERE SERIES, ASYMPTOTIC EXPANSION FOR X
C TO INFINITY AND ASYMPTOTIC EXPANSION FOR NU TO INFINITY ARE
C APPLIED.
C
IF (SXO2.LE.(FNU+1.0D0)) GO TO 90
TA = MAX(20.0D0,FNU)
IF (X.GT.TA) GO TO 120
IF (X.GT.12.0D0) GO TO 110
XO2L = LOG(XO2)
NS = INT(SXO2-FNU) + 1
GO TO 100
90 FN = FNU
FNP1 = FN + 1.0D0
XO2L = LOG(XO2)
IS = KT
IF (X.LE.0.50D0) GO TO 330
NS = 0
100 FNI = FNI + NS
DFN = FNI + FNF
FN = DFN
FNP1 = FN + 1.0D0
IS = KT
IF (N-1+NS.GT.0) IS = 3
GO TO 330
110 ANS = MAX(36.0D0-FNU,0.0D0)
NS = INT(ANS)
FNI = FNI + NS
DFN = FNI + FNF
FN = DFN
IS = KT
IF (N-1+NS.GT.0) IS = 3
GO TO 130
120 CONTINUE
RTX = SQRT(X)
TAU = RTWO*RTX
TA = TAU + FNULIM(KT)
IF (FNU.LE.TA) GO TO 480
FN = FNU
IS = KT
C
C UNIFORM ASYMPTOTIC EXPANSION FOR NU TO INFINITY
C
130 CONTINUE
I1 = ABS(3-IS)
I1 = MAX(I1,1)
FLGJY = 1.0D0
CALL DASYJY(DJAIRY,X,FN,FLGJY,I1,TEMP(IS),WK,IFLW)
IF(IFLW.NE.0) GO TO 380
GO TO (320, 450, 620), IS
310 TEMP(1) = TEMP(3)
KT = 1
320 IS = 2
FNI = FNI - 1.0D0
DFN = FNI + FNF
FN = DFN
IF(I1.EQ.2) GO TO 450
GO TO 130
C
C SERIES FOR (X/2)**2.LE.NU+1
C
330 CONTINUE
GLN = DLNGAM(FNP1)
ARG = FN*XO2L - GLN
IF (ARG.LT.(-ELIM1)) GO TO 400
EARG = EXP(ARG)
340 CONTINUE
S = 1.0D0
IF (X.LT.TOL) GO TO 360
AK = 3.0D0
T2 = 1.0D0
T = 1.0D0
S1 = FN
DO 350 K=1,17
S2 = T2 + S1
T = -T*SXO2/S2
S = S + T
IF (ABS(T).LT.TOL) GO TO 360
T2 = T2 + AK
AK = AK + 2.0D0
S1 = S1 + FN
350 CONTINUE
360 CONTINUE
TEMP(IS) = S*EARG
GO TO (370, 450, 610), IS
370 EARG = EARG*FN/XO2
FNI = FNI - 1.0D0
DFN = FNI + FNF
FN = DFN
IS = 2
GO TO 340
C
C SET UNDERFLOW VALUE AND UPDATE PARAMETERS
C UNDERFLOW CAN ONLY OCCUR FOR NS=0 SINCE THE ORDER MUST BE LARGER
C THAN 36. THEREFORE, NS NEE NOT BE TESTED.
C
380 Y(NN) = 0.0D0
NN = NN - 1
FNI = FNI - 1.0D0
DFN = FNI + FNF
FN = DFN
IF (NN-1) 440, 390, 130
390 KT = 2
IS = 2
GO TO 130
400 Y(NN) = 0.0D0
NN = NN - 1
FNP1 = FN
FNI = FNI - 1.0D0
DFN = FNI + FNF
FN = DFN
IF (NN-1) 440, 410, 420
410 KT = 2
IS = 2
420 IF (SXO2.LE.FNP1) GO TO 430
GO TO 130
430 ARG = ARG - XO2L + LOG(FNP1)
IF (ARG.LT.(-ELIM1)) GO TO 400
GO TO 330
440 NZ = N - NN
RETURN
C
C BACKWARD RECURSION SECTION
C
450 CONTINUE
IF(NS.NE.0) GO TO 451
NZ = N - NN
IF (KT.EQ.2) GO TO 470
C BACKWARD RECUR FROM INDEX ALPHA+NN-1 TO ALPHA
Y(NN) = TEMP(1)
Y(NN-1) = TEMP(2)
IF (NN.EQ.2) RETURN
451 CONTINUE
TRX = 2.0D0/X
DTM = FNI
TM = (DTM+FNF)*TRX
AK=1.0D0
TA=TEMP(1)
TB=TEMP(2)
IF(ABS(TA).GT.SLIM) GO TO 455
TA=TA*RTOL
TB=TB*RTOL
AK=TOL
455 CONTINUE
KK=2
IN=NS-1
IF(IN.EQ.0) GO TO 690
IF(NS.NE.0) GO TO 670
K=NN-2
DO 460 I=3,NN
S=TB
TB = TM*TB - TA
TA=S
Y(K)=TB*AK
DTM = DTM - 1.0D0
TM = (DTM+FNF)*TRX
K = K - 1
460 CONTINUE
RETURN
470 Y(1) = TEMP(2)
RETURN
C
C ASYMPTOTIC EXPANSION FOR X TO INFINITY WITH FORWARD RECURSION IN
C OSCILLATORY REGION X.GT.MAX(20, NU), PROVIDED THE LAST MEMBER
C OF THE SEQUENCE IS ALSO IN THE REGION.
C
480 CONTINUE
IN = INT(ALPHA-TAU+2.0D0)
IF (IN.LE.0) GO TO 490
IDALP = IALP - IN - 1
KT = 1
GO TO 500
490 CONTINUE
IDALP = IALP
IN = 0
500 IS = KT
FIDAL = IDALP
DALPHA = FIDAL + FNF
ARG = X - PIDT*DALPHA - PDF
SA = SIN(ARG)
SB = COS(ARG)
COEF = RTTP/RTX
ETX = 8.0D0*X
510 CONTINUE
DTM = FIDAL + FIDAL
DTM = DTM*DTM
TM = 0.0D0
IF (FIDAL.EQ.0.0D0 .AND. ABS(FNF).LT.TOL) GO TO 520
TM = 4.0D0*FNF*(FIDAL+FIDAL+FNF)
520 CONTINUE
TRX = DTM - 1.0D0
T2 = (TRX+TM)/ETX
S2 = T2
RELB = TOL*ABS(T2)
T1 = ETX
S1 = 1.0D0
FN = 1.0D0
AK = 8.0D0
DO 530 K=1,13
T1 = T1 + ETX
FN = FN + AK
TRX = DTM - FN
AP = TRX + TM
T2 = -T2*AP/T1
S1 = S1 + T2
T1 = T1 + ETX
AK = AK + 8.0D0
FN = FN + AK
TRX = DTM - FN
AP = TRX + TM
T2 = T2*AP/T1
S2 = S2 + T2
IF (ABS(T2).LE.RELB) GO TO 540
AK = AK + 8.0D0
530 CONTINUE
540 TEMP(IS) = COEF*(S1*SB-S2*SA)
IF(IS.EQ.2) GO TO 560
FIDAL = FIDAL + 1.0D0
DALPHA = FIDAL + FNF
IS = 2
TB = SA
SA = -SB
SB = TB
GO TO 510
C
C FORWARD RECURSION SECTION
C
560 IF (KT.EQ.2) GO TO 470
S1 = TEMP(1)
S2 = TEMP(2)
TX = 2.0D0/X
TM = DALPHA*TX
IF (IN.EQ.0) GO TO 580
C
C FORWARD RECUR TO INDEX ALPHA
C
DO 570 I=1,IN
S = S2
S2 = TM*S2 - S1
TM = TM + TX
S1 = S
570 CONTINUE
IF (NN.EQ.1) GO TO 600
S = S2
S2 = TM*S2 - S1
TM = TM + TX
S1 = S
580 CONTINUE
C
C FORWARD RECUR FROM INDEX ALPHA TO ALPHA+N-1
C
Y(1) = S1
Y(2) = S2
IF (NN.EQ.2) RETURN
DO 590 I=3,NN
Y(I) = TM*Y(I-1) - Y(I-2)
TM = TM + TX
590 CONTINUE
RETURN
600 Y(1) = S2
RETURN
C
C BACKWARD RECURSION WITH NORMALIZATION BY
C ASYMPTOTIC EXPANSION FOR NU TO INFINITY OR POWER SERIES.
C
610 CONTINUE
C COMPUTATION OF LAST ORDER FOR SERIES NORMALIZATION
AKM = MAX(3.0D0-FN,0.0D0)
KM = INT(AKM)
TFN = FN + KM
TA = (GLN+TFN-0.9189385332D0-0.0833333333D0/TFN)/(TFN+0.5D0)
TA = XO2L - TA
TB = -(1.0D0-1.5D0/TFN)/TFN
AKM = TOLLN/(-TA+SQRT(TA*TA-TOLLN*TB)) + 1.5D0
IN = KM + INT(AKM)
GO TO 660
620 CONTINUE
C COMPUTATION OF LAST ORDER FOR ASYMPTOTIC EXPANSION NORMALIZATION
GLN = WK(3) + WK(2)
IF (WK(6).GT.30.0D0) GO TO 640
RDEN = (PP(4)*WK(6)+PP(3))*WK(6) + 1.0D0
RZDEN = PP(1) + PP(2)*WK(6)
TA = RZDEN/RDEN
IF (WK(1).LT.0.10D0) GO TO 630
TB = GLN/WK(5)
GO TO 650
630 TB=(1.259921049D0+(0.1679894730D0+0.0887944358D0*WK(1))*WK(1))
1 /WK(7)
GO TO 650
640 CONTINUE
TA = 0.5D0*TOLLN/WK(4)
TA=((0.0493827160D0*TA-0.1111111111D0)*TA+0.6666666667D0)*TA*WK(6)
IF (WK(1).LT.0.10D0) GO TO 630
TB = GLN/WK(5)
650 IN = INT(TA/TB+1.5D0)
IF (IN.GT.INLIM) GO TO 310
660 CONTINUE
DTM = FNI + IN
TRX = 2.0D0/X
TM = (DTM+FNF)*TRX
TA = 0.0D0
TB = TOL
KK = 1
AK=1.0D0
670 CONTINUE
C
C BACKWARD RECUR UNINDEXED
C
DO 680 I=1,IN
S = TB
TB = TM*TB - TA
TA = S
DTM = DTM - 1.0D0
TM = (DTM+FNF)*TRX
680 CONTINUE
C NORMALIZATION
IF (KK.NE.1) GO TO 690
S=TEMP(3)
SA=TA/TB
TA=S
TB=S
IF(ABS(S).GT.SLIM) GO TO 685
TA=TA*RTOL
TB=TB*RTOL
AK=TOL
685 CONTINUE
TA=TA*SA
KK = 2
IN = NS
IF (NS.NE.0) GO TO 670
690 Y(NN) = TB*AK
NZ = N - NN
IF (NN.EQ.1) RETURN
K = NN - 1
S=TB
TB = TM*TB - TA
TA=S
Y(K)=TB*AK
IF (NN.EQ.2) RETURN
DTM = DTM - 1.0D0
TM = (DTM+FNF)*TRX
K=NN-2
C
C BACKWARD RECUR INDEXED
C
DO 700 I=3,NN
S=TB
TB = TM*TB - TA
TA=S
Y(K)=TB*AK
DTM = DTM - 1.0D0
TM = (DTM+FNF)*TRX
K = K - 1
700 CONTINUE
RETURN
C
C
C
710 CONTINUE
CALL XERMSG ('SLATEC', 'DBESJ', 'ORDER, ALPHA, LESS THAN ZERO.',
+ 2, 1)
RETURN
720 CONTINUE
CALL XERMSG ('SLATEC', 'DBESJ', 'N LESS THAN ONE.', 2, 1)
RETURN
730 CONTINUE
CALL XERMSG ('SLATEC', 'DBESJ', 'X LESS THAN ZERO.', 2, 1)
RETURN
END