https://github.com/cran/fOptions
Tip revision: 880bace785eda2a23173c060f1de08821872cc36 authored by Diethelm Wuertz on 08 August 1977, 00:00:00 UTC
version 191.10057
version 191.10057
Tip revision: 880bace
EBMconhyp.f
C ALGORITHM 707, COLLECTED ALGORITHMS FROM ACM.
C THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE,
C VOL. 18, NO. 3, SEPTEMBER, 1992, PP. 345-349.
C ****************************************************************
C * *
C * SOLUTION TO THE CONFLUENT HYPERGEOMETRIC FUNCTION *
C * *
C * by *
C * *
C * MARK NARDIN, *
C * *
C * W. F. PERGER and ATUL BHALLA *
C * *
C * *
C * Michigan Technological University, Copyright 1989 *
C * *
C * *
C * Description : A numerical evaluator for the confluent *
C * hypergeometric function for complex arguments with large *
C * magnitudes using a direct summation of the Kummer series. *
C * The method used allows an accuracy of up to thirteen *
C * decimal places through the use of large real arrays *
C * and a single final division. LNCHF is a variable which *
C * selects how the result should be represented. A '0' will *
C * return the value in standard exponential form. A '1' *
C * will return the LOG of the result. IP is an integer *
C * variable that specifies how many array positions are *
C * desired (usually 10 is sufficient). Setting IP=0 causes *
C * the program to estimate the number of array positions. *
C * *
C * The confluent hypergeometric function is the solution to *
C * the differential equation: *
C * *
C * zf"(z) + (a-z)f'(z) - bf(z) = 0 *
C * *
C * Subprograms called: BITS, CHGF *
C * *
C ****************************************************************
FUNCTION CONHYP (A,B,Z,LNCHF,IP)
INTEGER LNCHF,I,BITS,IP
COMPLEX*16 CHGF,A,B,Z,CONHYP
DOUBLE PRECISION NTERM,FX,TERM1,MAX,TERM2,ANG
IF (CDABS(Z) .NE. 0.0D0) THEN
ANG=DATAN2(DIMAG(Z),DBLE(Z))
ELSE
ANG=1.0D0
ENDIF
IF (DABS(ANG) .LT. (3.14159D0*0.5)) THEN
ANG=1.0D0
ELSE
ANG=DSIN(DABS(ANG)-(3.14159265D0*0.5D0))+1.0D0
ENDIF
MAX=0
NTERM=0
FX=0
TERM1=0
10 NTERM=NTERM+1
TERM2=CDABS((A+NTERM-1)*Z/((B+NTERM-1)*NTERM))
IF (TERM2 .EQ. 0.0D0) GOTO 20
IF (TERM2 .LT. 1.0D0) THEN
IF ((DBLE(A)+NTERM-1) .GT. 1.0D0) THEN
IF ((DBLE(B)+NTERM-1) .GT. 1.0D0) THEN
IF ((TERM2-TERM1) .LT. 0.0D0) THEN
GOTO 20
ENDIF
ENDIF
ENDIF
ENDIF
FX=FX+DLOG(TERM2)
IF (FX .GT. MAX) MAX=FX
TERM1=TERM2
GOTO 10
20 MAX=MAX*2/(BITS()*6.93147181D-1)
I=INT(MAX*ANG)+7
IF (I .LT. 5) I=5
IF (IP .GT. I) I=IP
CONHYP=CHGF(A,B,Z,I,LNCHF)
RETURN
END
C ****************************************************************
C * *
C * FUNCTION BITS *
C * *
C * *
C * Description : Determines the number of significant figures *
C * of machine precision to arrive at the size of the array *
C * the numbers must must be stored in to get the accuracy *
C * of the solution. *
C * *
C * Subprogram called: STORE *
C * *
C ****************************************************************
INTEGER FUNCTION BITS()
DOUBLE PRECISION BIT,BIT2,STORE
INTEGER COUNT
BIT=1.0
COUNT=0
10 COUNT=COUNT+1
BIT2=STORE(BIT*2.0)
BIT=STORE(BIT2+1.0)
IF ((BIT-BIT2) .NE. 0.0) GOTO 10
BITS=COUNT
RETURN
END
DOUBLE PRECISION FUNCTION STORE (X)
DOUBLE PRECISION X
C
C***********************************************************
C
C
C This function forces its argument X to be stored in a
C memory location, thus providing a means of determining
C floating point number characteristics (such as the machine
C precision) when it is necessary to avoid computation in
C high precision registers.
C
C On input:
C
C X = Value to be stored.
C
C X is not altered by this function.
C
C On output:
C
C STORE = Value of X after it has been stored and
C possibly truncated or rounded to the double
C precision word length.
C
C Modules required by STORE: None
C
C***********************************************************
C
DOUBLE PRECISION Y
COMMON/STCOM/Y
Y = X
STORE = Y
RETURN
END
C ****************************************************************
C * *
C * FUNCTION CHGF *
C * *
C * *
C * Description : Function that sums the Kummer series and *
C * returns the solution of the confluent hypergeometric *
C * function. *
C * *
C * Subprograms called: ARMULT, ARYDIV, BITS, CMPADD, CMPMUL *
C * *
C ****************************************************************
FUNCTION CHGF (A,B,Z,L,LNCHF)
PARAMETER (LENGTH=777)
INTEGER L,I,BITS,BIT,LNCHF
COMPLEX*16 A,B,Z,FINAL,CHGF
DOUBLE PRECISION AR,AI,CR,CI,XR,XI,SUMR,SUMI,CNT,SIGFIG,MX1,MX2
DOUBLE PRECISION NUMR,NUMI,DENOMR,DENOMI,RMAX
DOUBLE PRECISION QR1,QR2,QI1,QI2,AR2,AI2,CR2,CI2,XR2,XI2
DIMENSION SUMR(-1:LENGTH),SUMI(-1:LENGTH),NUMR(-1:LENGTH)
DIMENSION NUMI(-1:LENGTH),DENOMR(-1:LENGTH),DENOMI(-1:LENGTH)
DIMENSION QR1(-1:LENGTH),QR2(-1:LENGTH),QI1(-1:LENGTH),
: QI2(-1:LENGTH)
BIT=BITS()
RMAX=2.0D0**(BIT/2)
SIGFIG=2.0D0**(BIT/4)
AR2=DBLE(A)*SIGFIG
AR=DINT(AR2)
AR2=DNINT((AR2-AR)*RMAX)
AI2=DIMAG(A)*SIGFIG
AI=DINT(AI2)
AI2=DNINT((AI2-AI)*RMAX)
CR2=DBLE(B)*SIGFIG
CR=DINT(CR2)
CR2=DNINT((CR2-CR)*RMAX)
CI2=DIMAG(B)*SIGFIG
CI=DINT(CI2)
CI2=DNINT((CI2-CI)*RMAX)
XR2=DBLE(Z)*SIGFIG
XR=DINT(XR2)
XR2=DNINT((XR2-XR)*RMAX)
XI2=DIMAG(Z)*SIGFIG
XI=DINT(XI2)
XI2=DNINT((XI2-XI)*RMAX)
SUMR(-1)=1.0D0
SUMI(-1)=1.0D0
NUMR(-1)=1.0D0
NUMI(-1)=1.0D0
DENOMR(-1)=1.0D0
DENOMI(-1)=1.0D0
DO 100 I=0,L+1
SUMR(I)=0.0D0
SUMI(I)=0.0D0
NUMR(I)=0.0D0
NUMI(I)=0.0D0
DENOMR(I)=0.0D0
DENOMI(I)=0.0D0
100 CONTINUE
SUMR(1)=1.0D0
NUMR(1)=1.0D0
DENOMR(1)=1.0D0
CNT=SIGFIG
110 IF (SUMR(1) .LT. 0.5) THEN
MX1=SUMI(L+1)
ELSE IF (SUMI(1) .LT. 0.5) THEN
MX1=SUMR(L+1)
ELSE
MX1=DMAX1(SUMR(L+1),SUMI(L+1))
ENDIF
IF (NUMR(1) .LT. 0.5) THEN
MX2=NUMI(L+1)
ELSE IF (NUMI(1) .LT. 0.5) THEN
MX2=NUMR(L+1)
ELSE
MX2=DMAX1(NUMR(L+1),NUMI(L+1))
ENDIF
IF (MX1-MX2 .GT. 2.0) THEN
IF (CR .GT. 0.0D0) THEN
IF (CDABS(CMPLX(AR,AI)*CMPLX(XR,XI)/(CMPLX(CR,CI)*CNT))
: .LE. 1.0D0) GOTO 190
ENDIF
ENDIF
CALL CMPMUL(SUMR,SUMI,CR,CI,QR1,QI1,L,RMAX)
CALL CMPMUL(SUMR,SUMI,CR2,CI2,QR2,QI2,L,RMAX)
QR2(L+1)=QR2(L+1)-1
QI2(L+1)=QI2(L+1)-1
CALL CMPADD(QR1,QI1,QR2,QI2,SUMR,SUMI,L,RMAX)
CALL ARMULT(SUMR,CNT,SUMR,L,RMAX)
CALL ARMULT(SUMI,CNT,SUMI,L,RMAX)
CALL CMPMUL(DENOMR,DENOMI,CR,CI,QR1,QI1,L,RMAX)
CALL CMPMUL(DENOMR,DENOMI,CR2,CI2,QR2,QI2,L,RMAX)
QR2(L+1)=QR2(L+1)-1
QI2(L+1)=QI2(L+1)-1
CALL CMPADD(QR1,QI1,QR2,QI2,DENOMR,DENOMI,L,RMAX)
CALL ARMULT(DENOMR,CNT,DENOMR,L,RMAX)
CALL ARMULT(DENOMI,CNT,DENOMI,L,RMAX)
CALL CMPMUL(NUMR,NUMI,AR,AI,QR1,QI1,L,RMAX)
CALL CMPMUL(NUMR,NUMI,AR2,AI2,QR2,QI2,L,RMAX)
QR2(L+1)=QR2(L+1)-1
QI2(L+1)=QI2(L+1)-1
CALL CMPADD(QR1,QI1,QR2,QI2,NUMR,NUMI,L,RMAX)
CALL CMPMUL(NUMR,NUMI,XR,XI,QR1,QI1,L,RMAX)
CALL CMPMUL(NUMR,NUMI,XR2,XI2,QR2,QI2,L,RMAX)
QR2(L+1)=QR2(L+1)-1
QI2(L+1)=QI2(L+1)-1
CALL CMPADD(QR1,QI1,QR2,QI2,NUMR,NUMI,L,RMAX)
CALL CMPADD(SUMR,SUMI,NUMR,NUMI,SUMR,SUMI,L,RMAX)
CNT=CNT+SIGFIG
AR=AR+SIGFIG
CR=CR+SIGFIG
GOTO 110
190 CALL ARYDIV(SUMR,SUMI,DENOMR,DENOMI,FINAL,L,LNCHF,RMAX,BIT)
CHGF=FINAL
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE ARADD *
C * *
C * *
C * Description : Accepts two arrays of numbers and returns *
C * the sum of the array. Each array is holding the value *
C * of one number in the series. The parameter L is the *
C * size of the array representing the number and RMAX is *
C * the actual number of digits needed to give the numbers *
C * the desired accuracy. *
C * *
C * Subprograms called: none *
C * *
C ****************************************************************
SUBROUTINE ARADD(A,B,C,L,RMAX)
INTEGER L
DOUBLE PRECISION A,B,C,Z,RMAX
INTEGER EDIFF,I,J
DIMENSION A(-1:*),B(-1:*),C(-1:*),Z(-1:777)
DO 110 I=0,L+1
Z(I)=0.0D0
110 CONTINUE
EDIFF=DNINT(A(L+1)-B(L+1))
IF (DABS(A(1)) .LT. 0.5 .OR. EDIFF .LE. -L) GOTO 111
IF (DABS(B(1)) .LT. 0.5 .OR. EDIFF .GE. L) GOTO 113
GOTO 115
111 DO 112 I=-1,L+1
C(I)=B(I)
112 CONTINUE
GOTO 311
113 DO 114 I=-1,L+1
C(I)=A(I)
114 CONTINUE
GOTO 311
115 Z(-1)=A(-1)
IF (DABS(A(-1)-B(-1)) .LT. 0.5) GOTO 200
IF (EDIFF .GT. 0) THEN
Z(L+1)=A(L+1)
GOTO 233
ENDIF
IF (EDIFF .LT. 0) THEN
Z(L+1)=B(L+1)
Z(-1)=B(-1)
GOTO 266
ENDIF
DO 120 I=1,L
IF (A(I) .GT. B(I)) THEN
Z(L+1)=A(L+1)
GOTO 233
ENDIF
IF (A(I) .LT. B(I)) THEN
Z(L+1)=B(L+1)
Z(-1)=B(-1)
GOTO 266
ENDIF
120 CONTINUE
GOTO 300
200 IF (EDIFF .GT. 0) GOTO 203
IF (EDIFF .LT. 0) GOTO 207
Z(L+1)=A(L+1)
DO 201 I=L,1,-1
Z(I)=A(I)+B(I)+Z(I)
IF (Z(I) .GE. RMAX) THEN
Z(I)=Z(I)-RMAX
Z(I-1)=1.0D0
ENDIF
201 CONTINUE
IF (Z(0) .GT. 0.5) THEN
DO 202 I=L,1,-1
Z(I)=Z(I-1)
202 CONTINUE
Z(L+1)=Z(L+1)+1.0D0
Z(0)=0.0D0
ENDIF
GOTO 300
203 Z(L+1)=A(L+1)
DO 204 I=L,1+EDIFF,-1
Z(I)=A(I)+B(I-EDIFF)+Z(I)
IF (Z(I) .GE. RMAX) THEN
Z(I)=Z(I)-RMAX
Z(I-1)=1.0D0
ENDIF
204 CONTINUE
DO 205 I=EDIFF,1,-1
Z(I)=A(I)+Z(I)
IF (Z(I) .GE. RMAX) THEN
Z(I)=Z(I)-RMAX
Z(I-1)=1.0D0
ENDIF
205 CONTINUE
IF (Z(0) .GT. 0.5) THEN
DO 206 I=L,1,-1
Z(I)=Z(I-1)
206 CONTINUE
Z(L+1)=Z(L+1)+1
Z(0)=0.0D0
ENDIF
GOTO 300
207 Z(L+1)=B(L+1)
DO 208 I=L,1-EDIFF,-1
Z(I)=A(I+EDIFF)+B(I)+Z(I)
IF (Z(I) .GE. RMAX) THEN
Z(I)=Z(I)-RMAX
Z(I-1)=1.0D0
ENDIF
208 CONTINUE
DO 209 I=0-EDIFF,1,-1
Z(I)=B(I)+Z(I)
IF (Z(I) .GE. RMAX) THEN
Z(I)=Z(I)-RMAX
Z(I-1)=1.0D0
ENDIF
209 CONTINUE
IF (Z(0) .GT. 0.5) THEN
DO 210 I=L,1,-1
Z(I)=Z(I-1)
210 CONTINUE
Z(L+1)=Z(L+1)+1.0D0
Z(0)=0.0D0
ENDIF
GOTO 300
233 IF (EDIFF .GT. 0) GOTO 243
DO 234 I=L,1,-1
Z(I)=A(I)-B(I)+Z(I)
IF (Z(I) .LT. 0.0D0) THEN
Z(I)=Z(I)+RMAX
Z(I-1)=-1.0D0
ENDIF
234 CONTINUE
GOTO 290
243 DO 244 I=L,1+EDIFF,-1
Z(I)=A(I)-B(I-EDIFF)+Z(I)
IF (Z(I) .LT. 0.0D0) THEN
Z(I)=Z(I)+RMAX
Z(I-1)=-1.0D0
ENDIF
244 CONTINUE
DO 245 I=EDIFF,1,-1
Z(I)=A(I)+Z(I)
IF (Z(I) .LT. 0.0D0) THEN
Z(I)=Z(I)+RMAX
Z(I-1)=-1.0D0
ENDIF
245 CONTINUE
GOTO 290
266 IF (EDIFF .LT. 0) GOTO 276
DO 267 I=L,1,-1
Z(I)=B(I)-A(I)+Z(I)
IF (Z(I) .LT. 0.0D0) THEN
Z(I)=Z(I)+RMAX
Z(I-1)=-1.0D0
ENDIF
267 CONTINUE
GOTO 290
276 DO 277 I=L,1-EDIFF,-1
Z(I)=B(I)-A(I+EDIFF)+Z(I)
IF (Z(I) .LT. 0.0D0) THEN
Z(I)=Z(I)+RMAX
Z(I-1)=-1.0D0
ENDIF
277 CONTINUE
DO 278 I=0-EDIFF,1,-1
Z(I)=B(I)+Z(I)
IF (Z(I) .LT. 0.0D0) THEN
Z(I)=Z(I)+RMAX
Z(I-1)=-1.0D0
ENDIF
278 CONTINUE
290 IF (Z(1) .GT. 0.5) GOTO 300
I=1
291 I=I+1
IF (Z(I) .LT. 0.5 .AND. I .LT. L+1) GOTO 291
IF (I .EQ. L+1) THEN
Z(-1)=1.0D0
Z(L+1)=0.0D0
GOTO 300
ENDIF
292 DO 293 J=1,L+1-I
Z(J)=Z(J+I-1)
293 CONTINUE
DO 294 J=L+2-I,L
Z(J)=0.0D0
294 CONTINUE
Z(L+1)=Z(L+1)-I+1
300 DO 310 I=-1,L+1
C(I)=Z(I)
310 CONTINUE
311 IF (C(1) .LT. 0.5) THEN
C(-1)=1.0D0
C(L+1)=0.0D0
ENDIF
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE ARSUB *
C * *
C * *
C * Description : Accepts two arrays and subtracts each element *
C * in the second array from the element in the first array *
C * and returns the solution. The parameters L and RMAX are *
C * the size of the array and the number of digits needed for *
C * the accuracy, respectively. *
C * *
C * Subprograms called: ARADD *
C * *
C ****************************************************************
SUBROUTINE ARSUB(A,B,C,L,RMAX)
INTEGER L,I
DOUBLE PRECISION A,B,C,B2,RMAX
DIMENSION A(-1:*),B(-1:*),C(-1:*),B2(-1:777)
DO 100 I=-1,L+1
B2(I)=B(I)
100 CONTINUE
B2(-1)=(-1.0D0)*B2(-1)
CALL ARADD(A,B2,C,L,RMAX)
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE ARMULT *
C * *
C * *
C * Description : Accepts two arrays and returns the product. *
C * L and RMAX are the size of the arrays and the number of *
C * digits needed to represent the numbers with the required *
C * accuracy. *
C * *
C * Subprograms called: none *
C * *
C ****************************************************************
SUBROUTINE ARMULT(A,B,C,L,RMAX)
INTEGER L
DOUBLE PRECISION A,B,C,Z,B2,CARRY,RMAX,RMAX2
DIMENSION A(-1:*),C(-1:*),Z(-1:777)
INTEGER I
RMAX2=1.0D0/RMAX
Z(-1)=DSIGN(1.0D0,B)*A(-1)
B2=DABS(B)
Z(L+1)=A(L+1)
DO 100 I=0,L
Z(I)=0.0D0
100 CONTINUE
IF (B2 .LE. 1.0D-10 .OR. A(1) .LE. 1.0D-10) THEN
Z(-1)=1.0D0
Z(L+1)=0.0D0
GOTO 198
ENDIF
DO 110 I=L,1,-1
Z(I)=A(I)*B2+Z(I)
IF (Z(I) .GE. RMAX) THEN
CARRY=DINT(Z(I)/RMAX)
Z(I)=Z(I)-CARRY*RMAX
Z(I-1)=CARRY
ENDIF
110 CONTINUE
IF (Z(0) .LT. 0.5) GOTO 150
DO 120 I=L,1,-1
Z(I)=Z(I-1)
120 CONTINUE
Z(L+1)=Z(L+1)+1.0D0
Z(0)=0.0D0
150 CONTINUE
198 DO 199 I=-1,L+1
C(I)=Z(I)
199 CONTINUE
IF (C(1) .LT. 0.5) THEN
C(-1)=1.0D0
C(L+1)=0.0D0
ENDIF
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE CMPADD *
C * *
C * *
C * Description : Takes two arrays representing one real and *
C * one imaginary part, and adds two arrays representing *
C * another complex number and returns two array holding the *
C * complex sum. *
C * (CR,CI) = (AR+BR, AI+BI) *
C * *
C * Subprograms called: ARADD *
C * *
C ****************************************************************
SUBROUTINE CMPADD(AR,AI,BR,BI,CR,CI,L,RMAX)
INTEGER L
DOUBLE PRECISION AR,AI,BR,BI,CR,CI,RMAX
DIMENSION AR(-1:*),AI(-1:*),BR(-1:*),BI(-1:*)
DIMENSION CR(-1:*),CI(-1:*)
CALL ARADD(AR,BR,CR,L,RMAX)
CALL ARADD(AI,BI,CI,L,RMAX)
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE CMPSUB *
C * *
C * *
C * Description : Takes two arrays representing one real and *
C * one imaginary part, and subtracts two arrays representing *
C * another complex number and returns two array holding the *
C * complex sum. *
C * (CR,CI) = (AR+BR, AI+BI) *
C * *
C * Subprograms called: ARADD *
C * *
C ****************************************************************
SUBROUTINE CMPSUB(AR,AI,BR,BI,CR,CI,L,RMAX)
INTEGER L
DOUBLE PRECISION AR,AI,BR,BI,CR,CI,RMAX
DIMENSION AR(-1:*),AI(-1:*),BR(-1:*),BI(-1:*)
DIMENSION CR(-1:*),CI(-1:*)
CALL ARSUB(AR,BR,CR,L,RMAX)
CALL ARSUB(AI,BI,CI,L,RMAX)
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE CMPMUL *
C * *
C * *
C * Description : Takes two arrays representing one real and *
C * one imaginary part, and multiplies it with two arrays *
C * representing another complex number and returns the *
C * complex product. *
C * *
C * Subprograms called: ARMULT, ARSUB, ARADD *
C * *
C ****************************************************************
SUBROUTINE CMPMUL(AR,AI,BR,BI,CR,CI,L,RMAX)
INTEGER L
DOUBLE PRECISION AR,AI,BR,BI,CR,CI,D1,D2,RMAX
DIMENSION AR(-1:*),AI(-1:*),CR(-1:*),CI(-1:*)
DIMENSION D1(-1:777),D2(-1:777)
CALL ARMULT(AR,BR,D1,L,RMAX)
CALL ARMULT(AI,BI,D2,L,RMAX)
CALL ARSUB(D1,D2,CR,L,RMAX)
CALL ARMULT(AR,BI,D1,L,RMAX)
CALL ARMULT(AI,BR,D2,L,RMAX)
CALL ARADD(D1,D2,CI,L,RMAX)
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE ARYDIV *
C * *
C * *
C * Description : Returns the double precision complex number *
C * resulting from the division of four arrays, representing *
C * two complex numbers. The number returned will be in one *
C * two different forms. Either standard scientific or as *
C * the log of the number. *
C * *
C * Subprograms called: CONV21, CONV12, EADD, ECPDIV, EMULT *
C * *
C ****************************************************************
SUBROUTINE ARYDIV(AR,AI,BR,BI,C,L,LNCHF,RMAX,BIT)
INTEGER L,BIT,REXP,IR10,II10,LNCHF
COMPLEX*16 C
DOUBLE PRECISION AR,AI,BR,BI,PHI,N1,N2,N3,E1,E2,E3,RR10,RI10,X
DOUBLE PRECISION AE,BE,X1,X2,DUM1,DUM2,CE,RMAX
DIMENSION AR(-1:*),AI(-1:*),BR(-1:*),BI(-1:*)
DIMENSION AE(2,2),BE(2,2),CE(2,2)
REXP=BIT/2
X=REXP*(AR(L+1)-2)
RR10=X*DLOG10(2.0D0)/DLOG10(10.0D0)
IR10=INT(RR10)
RR10=RR10-IR10
X=REXP*(AI(L+1)-2)
RI10=X*DLOG10(2.0D0)/DLOG10(10.0D0)
II10=INT(RI10)
RI10=RI10-II10
DUM1=DSIGN(AR(1)*RMAX*RMAX+AR(2)*RMAX+AR(3),AR(-1))
DUM2=DSIGN(AI(1)*RMAX*RMAX+AI(2)*RMAX+AI(3),AI(-1))
DUM1=DUM1*10**RR10
DUM2=DUM2*10**RI10
CALL CONV12(DCMPLX(DUM1,DUM2),AE)
AE(1,2)=AE(1,2)+IR10
AE(2,2)=AE(2,2)+II10
X=REXP*(BR(L+1)-2)
RR10=X*DLOG10(2.0D0)/DLOG10(10.0D0)
IR10=INT(RR10)
RR10=RR10-IR10
X=REXP*(BI(L+1)-2)
RI10=X*DLOG10(2.0D0)/DLOG10(10.0D0)
II10=INT(RI10)
RI10=RI10-II10
DUM1=DSIGN(BR(1)*RMAX*RMAX+BR(2)*RMAX+BR(3),BR(-1))
DUM2=DSIGN(BI(1)*RMAX*RMAX+BI(2)*RMAX+BI(3),BI(-1))
DUM1=DUM1*10**RR10
DUM2=DUM2*10**RI10
CALL CONV12(DCMPLX(DUM1,DUM2),BE)
BE(1,2)=BE(1,2)+IR10
BE(2,2)=BE(2,2)+II10
CALL ECPDIV(AE,BE,CE)
IF (LNCHF .EQ. 0) THEN
CALL CONV21(CE,C)
ELSE
CALL EMULT(CE(1,1),CE(1,2),CE(1,1),CE(1,2),N1,E1)
CALL EMULT(CE(2,1),CE(2,2),CE(2,1),CE(2,2),N2,E2)
CALL EADD(N1,E1,N2,E2,N3,E3)
N1=CE(1,1)
E1=CE(1,2)-CE(2,2)
X2=CE(2,1)
IF (E1 .GT. 74.0D0) THEN
X1=1.0D75
ELSEIF (E1 .LT. -74.0D0) THEN
X1=0
ELSE
X1=N1*(10**E1)
ENDIF
PHI=DATAN2(X2,X1)
C=DCMPLX(0.50D0*(DLOG(N3)+E3*DLOG(10.0D0)),PHI)
ENDIF
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE EMULT *
C * *
C * *
C * Description : Takes one base and exponent and multiplies it *
C * by another numbers base and exponent to give the product *
C * in the form of base and exponent. *
C * *
C * Subprograms called: none *
C * *
C ****************************************************************
SUBROUTINE EMULT(N1,E1,N2,E2,NF,EF)
DOUBLE PRECISION N1,E1,N2,E2,NF,EF
NF=N1*N2
EF=E1+E2
IF (DABS(NF) .GE. 10.0D0) THEN
NF=NF/10.0D0
EF=EF+1.0D0
ENDIF
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE EDIV *
C * *
C * *
C * Description : returns the solution in the form of base and *
C * exponent of the division of two exponential numbers. *
C * *
C * Subprograms called: none *
C * *
C ****************************************************************
SUBROUTINE EDIV(N1,E1,N2,E2,NF,EF)
DOUBLE PRECISION N1,E1,N2,E2,NF,EF
NF=N1/N2
EF=E1-E2
IF ((DABS(NF) .LT. 1.0D0) .AND. (NF .NE. 0.0D0)) THEN
NF=NF*10.0D0
EF=EF-1.0D0
ENDIF
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE EADD *
C * *
C * *
C * Description : Returns the sum of two numbers in the form *
C * of a base and an exponent. *
C * *
C * Subprograms called: none *
C * *
C ****************************************************************
SUBROUTINE EADD(N1,E1,N2,E2,NF,EF)
DOUBLE PRECISION N1,E1,N2,E2,NF,EF,EDIFF
EDIFF=E1-E2
IF (EDIFF .GT. 36.0D0) THEN
NF=N1
EF=E1
ELSE IF (EDIFF .LT. -36.0D0) THEN
NF=N2
EF=E2
ELSE
NF=N1*(10.0D0**EDIFF)+N2
EF=E2
400 IF (DABS(NF) .LT. 10.0D0) GOTO 410
NF=NF/10.0D0
EF=EF+1.0D0
GOTO 400
410 IF ((DABS(NF) .GE. 1.0D0) .OR. (NF .EQ. 0.0D0)) GOTO 420
NF=NF*10.0D0
EF=EF-1.0D0
GOTO 410
ENDIF
420 RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE ESUB *
C * *
C * *
C * Description : Returns the solution to the subtraction of *
C * two numbers in the form of base and exponent. *
C * *
C * Subprograms called: EADD *
C * *
C ****************************************************************
SUBROUTINE ESUB(N1,E1,N2,E2,NF,EF)
DOUBLE PRECISION N1,E1,N2,E2,NF,EF
CALL EADD(N1,E1,N2*(-1.0D0),E2,NF,EF)
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE CONV12 *
C * *
C * *
C * Description : Converts a number from complex notation to a *
C * form of a 2x2 real array. *
C * *
C * Subprograms called: none *
C * *
C ****************************************************************
SUBROUTINE CONV12(CN,CAE)
COMPLEX*16 CN
DOUBLE PRECISION CAE
DIMENSION CAE(2,2)
CAE(1,1)=DBLE(CN)
CAE(1,2)=0.0D0
300 IF (DABS(CAE(1,1)) .LT. 10.0D0) GOTO 310
CAE(1,1)=CAE(1,1)/10.0D0
CAE(1,2)=CAE(1,2)+1.0D0
GOTO 300
310 IF ((DABS(CAE(1,1)) .GE. 1.0D0) .OR. (CAE(1,1) .EQ. 0.0D0))
: GOTO 320
CAE(1,1)=CAE(1,1)*10.0D0
CAE(1,2)=CAE(1,2)-1.0D0
GOTO 310
320 CAE(2,1)=DIMAG(CN)
CAE(2,2)=0.0D0
330 IF (DABS(CAE(2,1)) .LT. 10.0D0) GOTO 340
CAE(2,1)=CAE(2,1)/10.0D0
CAE(2,2)=CAE(2,2)+1.0D0
GOTO 330
340 IF ((DABS(CAE(2,1)) .GE. 1.0D0) .OR. (CAE(2,1) .EQ. 0.0D0))
: GOTO 350
CAE(2,1)=CAE(2,1)*10.0D0
CAE(2,2)=CAE(2,2)-1.0D0
GOTO 340
350 RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE CONV21 *
C * *
C * *
C * Description : Converts a number represented in a 2x2 real *
C * array to the form of a complex number. *
C * *
C * Subprograms called: none *
C * *
C ****************************************************************
SUBROUTINE CONV21(CAE,CN)
DOUBLE PRECISION CAE
COMPLEX*16 CN
DIMENSION CAE(2,2)
IF (CAE(1,2) .GT. 75 .OR. CAE(2,2) .GT. 75) THEN
CN=CMPLX(1.0D75,1.0D75)
ELSE IF (CAE(2,2) .LT. -75) THEN
CN=DCMPLX(CAE(1,1)*(10**CAE(1,2)),0D0)
ELSE
CN=DCMPLX(CAE(1,1)*(10**CAE(1,2)),CAE(2,1)*(10**CAE(2,2)))
ENDIF
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE ECPMUL *
C * *
C * *
C * Description : Multiplies two numbers which are each *
C * represented in the form of a two by two array and returns *
C * the solution in the same form. *
C * *
C * Subprograms called: EMULT, ESUB, EADD *
C * *
C ****************************************************************
SUBROUTINE ECPMUL(A,B,C)
DOUBLE PRECISION A,B,C,N1,E1,N2,E2,C2
DIMENSION A(2,2),B(2,2),C(2,2),C2(2,2)
CALL EMULT(A(1,1),A(1,2),B(1,1),B(1,2),N1,E1)
CALL EMULT(A(2,1),A(2,2),B(2,1),B(2,2),N2,E2)
CALL ESUB(N1,E1,N2,E2,C2(1,1),C2(1,2))
CALL EMULT(A(1,1),A(1,2),B(2,1),B(2,2),N1,E1)
CALL EMULT(A(2,1),A(2,2),B(1,1),B(1,2),N2,E2)
CALL EADD(N1,E1,N2,E2,C(2,1),C(2,2))
C(1,1)=C2(1,1)
C(1,2)=C2(1,2)
RETURN
END
C ****************************************************************
C * *
C * SUBROUTINE ECPDIV *
C * *
C * *
C * Description : Divides two numbers and returns the solution. *
C * All numbers are represented by a 2x2 array. *
C * *
C * Subprograms called: EADD, ECPMUL, EDIV, EMULT *
C * *
C ****************************************************************
SUBROUTINE ECPDIV(A,B,C)
DOUBLE PRECISION A,B,C,N1,E1,N2,E2,B2,N3,E3,C2
DIMENSION A(2,2),B(2,2),C(2,2),B2(2,2),C2(2,2)
B2(1,1)=B(1,1)
B2(1,2)=B(1,2)
B2(2,1)=-1.0D0*B(2,1)
B2(2,2)=B(2,2)
CALL ECPMUL(A,B2,C2)
CALL EMULT(B(1,1),B(1,2),B(1,1),B(1,2),N1,E1)
CALL EMULT(B(2,1),B(2,2),B(2,1),B(2,2),N2,E2)
CALL EADD(N1,E1,N2,E2,N3,E3)
CALL EDIV(C2(1,1),C2(1,2),N3,E3,C(1,1),C(1,2))
CALL EDIV(C2(2,1),C2(2,2),N3,E3,C(2,1),C(2,2))
RETURN
END
C ******************************************************************************
SUBROUTINE CHFM(ZRE,ZIM,ARE,AIM,BRE,BIM,CRE,CIM,N,LNCHF,IP)
REAL*8 ZRE(N), ZIM(N), CRE(N), CIM(N)
REAL*8 ARE, AIM, BRE, BIM
COMPLEX*16 Z, A, B, CHF, CONHYP
A = CMPLX(ARE, AIM)
B = CMPLX(BRE, BIM)
DO I=1,N
Z = CMPLX(ZRE(I), ZIM(I))
CHF = CONHYP(A, B, Z, LNCHF, IP)
CRE(I) = DREAL(CHF)
CIM(I) = DIMAG(CHF)
ENDDO
RETURN
END
C ******************************************************************************
C SUBROUTINE DRIVER_CHF()
C REAL*8 ZRE(2), ZIM(2), ARE, AIM, BRE, BIM, CRE(2), CIM(2)C
C ZRE(1) = 1.1D0
C ZIM(1) = 0.6D0
C ZRE(2) = -2.6D0
C ZIM(2) = 0.8D0
C ARE = 1.2D0
C AIM = 1.4D0
C BRE = 2.1D0
C BIM = 1.3D0
C LNCHF=0
C IP=0
C CALL CHFM(ZRE,ZIM,ARE,AIM,BRE,BIM,CRE,CIM,2,LNCHF,IP)
C WRITE (*,*) "M:"
C WRITE(*,*) ZRE(1), ZIM(1), CRE(1), CIM(1)
C WRITE(*,*) ZRE(2), ZIM(2), CRE(2), CIM(2)
C RETURN
C END
c PROGRAM TEST
c CALL DRIVER_CHF()
c STOP
c END