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

164 lines
4.8 KiB
Fortran

*DECK CSERI
SUBROUTINE CSERI (Z, FNU, KODE, N, Y, NZ, TOL, ELIM, ALIM)
C***BEGIN PROLOGUE CSERI
C***SUBSIDIARY
C***PURPOSE Subsidiary to CBESI and CBESK
C***LIBRARY SLATEC
C***TYPE ALL (CSERI-A, ZSERI-A)
C***AUTHOR Amos, D. E., (SNL)
C***DESCRIPTION
C
C CSERI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z).GE.0.0 BY
C MEANS OF THE POWER SERIES FOR LARGE ABS(Z) IN THE
C REGION ABS(Z).LE.2*SQRT(FNU+1). NZ=0 IS A NORMAL RETURN.
C NZ.GT.0 MEANS THAT THE LAST NZ COMPONENTS WERE SET TO ZERO
C DUE TO UNDERFLOW. NZ.LT.0 MEANS UNDERFLOW OCCURRED, BUT THE
C CONDITION ABS(Z).LE.2*SQRT(FNU+1) WAS VIOLATED AND THE
C COMPUTATION MUST BE COMPLETED IN ANOTHER ROUTINE WITH N=N-ABS(NZ).
C
C***SEE ALSO CBESI, CBESK
C***ROUTINES CALLED CUCHK, GAMLN, R1MACH
C***REVISION HISTORY (YYMMDD)
C 830501 DATE WRITTEN
C 910415 Prologue converted to Version 4.0 format. (BAB)
C***END PROLOGUE CSERI
COMPLEX AK1, CK, COEF, CONE, CRSC, CZ, CZERO, HZ, RZ, S1, S2, W,
* Y, Z
REAL AA, ACZ, AK, ALIM, ARM, ASCLE, ATOL, AZ, DFNU, ELIM, FNU,
* FNUP, RAK1, RS, RTR1, S, SS, TOL, X, GAMLN, R1MACH
INTEGER I, IB, IDUM, IFLAG, IL, K, KODE, L, M, N, NN, NW, NZ
DIMENSION Y(N), W(2)
DATA CZERO, CONE / (0.0E0,0.0E0), (1.0E0,0.0E0) /
C***FIRST EXECUTABLE STATEMENT CSERI
NZ = 0
AZ = ABS(Z)
IF (AZ.EQ.0.0E0) GO TO 150
X = REAL(Z)
ARM = 1.0E+3*R1MACH(1)
RTR1 = SQRT(ARM)
CRSC = CMPLX(1.0E0,0.0E0)
IFLAG = 0
IF (AZ.LT.ARM) GO TO 140
HZ = Z*CMPLX(0.5E0,0.0E0)
CZ = CZERO
IF (AZ.GT.RTR1) CZ = HZ*HZ
ACZ = ABS(CZ)
NN = N
CK = CLOG(HZ)
10 CONTINUE
DFNU = FNU + (NN-1)
FNUP = DFNU + 1.0E0
C-----------------------------------------------------------------------
C UNDERFLOW TEST
C-----------------------------------------------------------------------
AK1 = CK*CMPLX(DFNU,0.0E0)
AK = GAMLN(FNUP,IDUM)
AK1 = AK1 - CMPLX(AK,0.0E0)
IF (KODE.EQ.2) AK1 = AK1 - CMPLX(X,0.0E0)
RAK1 = REAL(AK1)
IF (RAK1.GT.(-ELIM)) GO TO 30
20 CONTINUE
NZ = NZ + 1
Y(NN) = CZERO
IF (ACZ.GT.DFNU) GO TO 170
NN = NN - 1
IF (NN.EQ.0) RETURN
GO TO 10
30 CONTINUE
IF (RAK1.GT.(-ALIM)) GO TO 40
IFLAG = 1
SS = 1.0E0/TOL
CRSC = CMPLX(TOL,0.0E0)
ASCLE = ARM*SS
40 CONTINUE
AK = AIMAG(AK1)
AA = EXP(RAK1)
IF (IFLAG.EQ.1) AA = AA*SS
COEF = CMPLX(AA,0.0E0)*CMPLX(COS(AK),SIN(AK))
ATOL = TOL*ACZ/FNUP
IL = MIN(2,NN)
DO 80 I=1,IL
DFNU = FNU + (NN-I)
FNUP = DFNU + 1.0E0
S1 = CONE
IF (ACZ.LT.TOL*FNUP) GO TO 60
AK1 = CONE
AK = FNUP + 2.0E0
S = FNUP
AA = 2.0E0
50 CONTINUE
RS = 1.0E0/S
AK1 = AK1*CZ*CMPLX(RS,0.0E0)
S1 = S1 + AK1
S = S + AK
AK = AK + 2.0E0
AA = AA*ACZ*RS
IF (AA.GT.ATOL) GO TO 50
60 CONTINUE
M = NN - I + 1
S2 = S1*COEF
W(I) = S2
IF (IFLAG.EQ.0) GO TO 70
CALL CUCHK(S2, NW, ASCLE, TOL)
IF (NW.NE.0) GO TO 20
70 CONTINUE
Y(M) = S2*CRSC
IF (I.NE.IL) COEF = COEF*CMPLX(DFNU,0.0E0)/HZ
80 CONTINUE
IF (NN.LE.2) RETURN
K = NN - 2
AK = K
RZ = (CONE+CONE)/Z
IF (IFLAG.EQ.1) GO TO 110
IB = 3
90 CONTINUE
DO 100 I=IB,NN
Y(K) = CMPLX(AK+FNU,0.0E0)*RZ*Y(K+1) + Y(K+2)
AK = AK - 1.0E0
K = K - 1
100 CONTINUE
RETURN
C-----------------------------------------------------------------------
C RECUR BACKWARD WITH SCALED VALUES
C-----------------------------------------------------------------------
110 CONTINUE
C-----------------------------------------------------------------------
C EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION ABOVE THE
C UNDERFLOW LIMIT = ASCLE = R1MACH(1)*CSCL*1.0E+3
C-----------------------------------------------------------------------
S1 = W(1)
S2 = W(2)
DO 120 L=3,NN
CK = S2
S2 = S1 + CMPLX(AK+FNU,0.0E0)*RZ*S2
S1 = CK
CK = S2*CRSC
Y(K) = CK
AK = AK - 1.0E0
K = K - 1
IF (ABS(CK).GT.ASCLE) GO TO 130
120 CONTINUE
RETURN
130 CONTINUE
IB = L + 1
IF (IB.GT.NN) RETURN
GO TO 90
140 CONTINUE
NZ = N
IF (FNU.EQ.0.0E0) NZ = NZ - 1
150 CONTINUE
Y(1) = CZERO
IF (FNU.EQ.0.0E0) Y(1) = CONE
IF (N.EQ.1) RETURN
DO 160 I=2,N
Y(I) = CZERO
160 CONTINUE
RETURN
C-----------------------------------------------------------------------
C RETURN WITH NZ.LT.0 IF ABS(Z*Z/4).GT.FNU+N-NZ-1 COMPLETE
C THE CALCULATION IN CBINU WITH N=N-ABS(NZ)
C-----------------------------------------------------------------------
170 CONTINUE
NZ = -NZ
RETURN
END