Files
gonum/mathext/internal/amos/origcode_test.go
2017-06-20 16:29:35 +09:30

2277 lines
51 KiB
Go

// Copyright ©2016 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package amos
import (
"math"
"math/cmplx"
)
// These routines are the versions directly modified from the Fortran code.
// They are used to ensure that code style improvements do not change the
// code output.
func iabs(a int) int {
if a >= 0 {
return a
}
return -a
}
func min0(a, b int) int {
if a < b {
return a
}
return b
}
func max0(a, b int) int {
if a > b {
return a
}
return b
}
func zairyOrig(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ int) {
// zairy is adapted from the original Netlib code by Donald Amos.
// http://www.netlib.no/netlib/amos/zairy.f
// Original comment:
/*
C***BEGIN PROLOGUE ZAIRY
C***DATE WRITTEN 830501 (YYMMDD)
C***REVISION DATE 890801 (YYMMDD)
C***CATEGORY NO. B5K
C***KEYWORDS AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD
C***AUTHOR AMOS, DONALD E., SANDIA NATIONAL LABORATORIES
C***PURPOSE TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z
C***DESCRIPTION
C
C ***A DOUBLE PRECISION ROUTINE***
C ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR
C ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON
C KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)*
C DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN
C -PI/3<ARG(Z)<PI/3 AND THE EXPONENTIAL GROWTH IN
C PI/3<ABS(ARG(Z))<PI WHERE ZTA=(2/3)*Z*CSQRT(Z).
C
C WHILE THE AIRY FUNCTIONS AI(Z) AND DAI(Z)/DZ ARE ANALYTIC IN
C THE WHOLE Z PLANE, THE CORRESPONDING SCALED FUNCTIONS DEFINED
C FOR KODE=2 HAVE A CUT ALONG THE NEGATIVE REAL AXIS.
C DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF
C MATHEMATICAL FUNCTIONS (REF. 1).
C
C INPUT ZR,ZI ARE DOUBLE PRECISION
C ZR,ZI - Z=CMPLX(ZR,ZI)
C ID - ORDER OF DERIVATIVE, ID=0 OR ID=1
C KODE - A PARAMETER TO INDICATE THE SCALING OPTION
C KODE= 1 returnS
C AI=AI(Z) ON ID=0 OR
C AI=DAI(Z)/DZ ON ID=1
C = 2 returnS
C AI=CEXP(ZTA)*AI(Z) ON ID=0 OR
C AI=CEXP(ZTA)*DAI(Z)/DZ ON ID=1 WHERE
C ZTA=(2/3)*Z*CSQRT(Z)
C
C OUTPUT AIR,AII ARE DOUBLE PRECISION
C AIR,AII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND
C KODE
C NZ - UNDERFLOW INDICATOR
C NZ= 0 , NORMAL return
C NZ= 1 , AI=CMPLX(0.0E0,0.0E0) DUE TO UNDERFLOW IN
C -PI/3<ARG(Z)<PI/3 ON KODE=1
C IERR - ERROR FLAG
C IERR=0, NORMAL return - COMPUTATION COMPLETED
C IERR=1, INPUT ERROR - NO COMPUTATION
C IERR=2, OVERFLOW - NO COMPUTATION, REAL(ZTA)
C TOO LARGE ON KODE=1
C IERR=3, CABS(Z) LARGE - COMPUTATION COMPLETED
C LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION
C PRODUCE LESS THAN HALF OF MACHINE ACCURACY
C IERR=4, CABS(Z) TOO LARGE - NO COMPUTATION
C COMPLETE LOSS OF ACCURACY BY ARGUMENT
C REDUCTION
C IERR=5, ERROR - NO COMPUTATION,
C ALGORITHM TERMINATION CONDITION NOT MET
C
C***LONG DESCRIPTION
C
C AI AND DAI ARE COMPUTED FOR CABS(Z)>1.0 FROM THE K BESSEL
C FUNCTIONS BY
C
C AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA)
C C=1.0/(PI*SQRT(3.0))
C ZTA=(2/3)*Z**(3/2)
C
C WITH THE POWER SERIES FOR CABS(Z)<=1.0.
C
C IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-
C MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES
C OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF
C THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR),
C THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR
C FLAG IERR=3 IS TRIGGERED WHERE UR=dmax(dmach[4),1.0D-18) IS
C DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.
C ALSO, if THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN
C ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT
C FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE
C LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA
C MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2,
C AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE
C PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE
C PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT-
C ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG-
C NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN
C DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN
C EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES,
C NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE
C PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER
C MACHINES.
C
C THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX
C BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT
C ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-
C SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE
C ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),
C ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF
C CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY
C HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN
C ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY
C SEVERAL ORDERS OF MAGNITUDE. if ONE COMPONENT IS 10**K LARGER
C THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,
C 0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS
C THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER
C COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY
C BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER
C COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE
C MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,
C THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,
C OR -PI/2+P.
C
C***REFERENCES HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ
C AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF
C COMMERCE, 1955.
C
C COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT
C AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983
C
C A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX
C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-
C 1018, MAY, 1985
C
C A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX
C ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.
C MATH. SOFTWARE, 1986
*/
var AI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3 complex128
var AA, AD, AK, ALIM, ATRM, AZ, AZ3, BK,
CC, CK, COEF, CONEI, CONER, CSQI, CSQR, C1, C2, DIG,
DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR,
S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI,
ZEROR, ZTAI, ZTAR, Z3I, Z3R, ALAZ, BB float64
var IERR, IFLAG, K, K1, K2, MR, NN int
var tmp complex128
// Extra element for padding.
CYR := []float64{math.NaN(), 0}
CYI := []float64{math.NaN(), 0}
_ = AI
_ = CONE
_ = CSQ
_ = CY
_ = S1
_ = S2
_ = TRM1
_ = TRM2
_ = Z
_ = ZTA
_ = Z3
TTH = 6.66666666666666667E-01
C1 = 3.55028053887817240E-01
C2 = 2.58819403792806799E-01
COEF = 1.83776298473930683E-01
ZEROR = 0
ZEROI = 0
CONER = 1
CONEI = 0
NZ = 0
if ID < 0 || ID > 1 {
IERR = 1
}
if KODE < 1 || KODE > 2 {
IERR = 1
}
if IERR != 0 {
return
}
AZ = zabs(complex(ZR, ZI))
TOL = dmax(dmach[4], 1.0E-18)
FID = float64(ID)
if AZ > 1.0E0 {
goto Seventy
}
// POWER SERIES FOR CABS(Z)<=1.
S1R = CONER
S1I = CONEI
S2R = CONER
S2I = CONEI
if AZ < TOL {
goto OneSeventy
}
AA = AZ * AZ
if AA < TOL/AZ {
goto Forty
}
TRM1R = CONER
TRM1I = CONEI
TRM2R = CONER
TRM2I = CONEI
ATRM = 1.0E0
STR = ZR*ZR - ZI*ZI
STI = ZR*ZI + ZI*ZR
Z3R = STR*ZR - STI*ZI
Z3I = STR*ZI + STI*ZR
AZ3 = AZ * AA
AK = 2.0E0 + FID
BK = 3.0E0 - FID - FID
CK = 4.0E0 - FID
DK = 3.0E0 + FID + FID
D1 = AK * DK
D2 = BK * CK
AD = dmin(D1, D2)
AK = 24.0E0 + 9.0E0*FID
BK = 30.0E0 - 9.0E0*FID
for K = 1; K <= 25; K++ {
STR = (TRM1R*Z3R - TRM1I*Z3I) / D1
TRM1I = (TRM1R*Z3I + TRM1I*Z3R) / D1
TRM1R = STR
S1R = S1R + TRM1R
S1I = S1I + TRM1I
STR = (TRM2R*Z3R - TRM2I*Z3I) / D2
TRM2I = (TRM2R*Z3I + TRM2I*Z3R) / D2
TRM2R = STR
S2R = S2R + TRM2R
S2I = S2I + TRM2I
ATRM = ATRM * AZ3 / AD
D1 = D1 + AK
D2 = D2 + BK
AD = dmin(D1, D2)
if ATRM < TOL*AD {
goto Forty
}
AK = AK + 18.0E0
BK = BK + 18.0E0
}
Forty:
if ID == 1 {
goto Fifty
}
AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I)
AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R)
if KODE == 1 {
return
}
tmp = zsqrt(complex(ZR, ZI))
STR = real(tmp)
STI = imag(tmp)
ZTAR = TTH * (ZR*STR - ZI*STI)
ZTAI = TTH * (ZR*STI + ZI*STR)
tmp = zexp(complex(ZTAR, ZTAI))
STR = real(tmp)
STI = imag(tmp)
PTR = AIR*STR - AII*STI
AII = AIR*STI + AII*STR
AIR = PTR
return
Fifty:
AIR = -S2R * C2
AII = -S2I * C2
if AZ <= TOL {
goto Sixty
}
STR = ZR*S1R - ZI*S1I
STI = ZR*S1I + ZI*S1R
CC = C1 / (1.0E0 + FID)
AIR = AIR + CC*(STR*ZR-STI*ZI)
AII = AII + CC*(STR*ZI+STI*ZR)
Sixty:
if KODE == 1 {
return
}
tmp = zsqrt(complex(ZR, ZI))
STR = real(tmp)
STI = imag(tmp)
ZTAR = TTH * (ZR*STR - ZI*STI)
ZTAI = TTH * (ZR*STI + ZI*STR)
tmp = zexp(complex(ZTAR, ZTAI))
STR = real(tmp)
STI = imag(tmp)
PTR = STR*AIR - STI*AII
AII = STR*AII + STI*AIR
AIR = PTR
return
// CASE FOR CABS(Z)>1.0.
Seventy:
FNU = (1.0E0 + FID) / 3.0E0
/*
SET PARAMETERS RELATED TO MACHINE CONSTANTS.
TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18.
ELIM IS THE APPROXIMATE EXPONENTIAL OVER-&&UNDERFLOW LIMIT.
EXP(-ELIM)<EXP(-ALIM)=EXP(-ELIM)/TOL AND
EXP(ELIM)>EXP(ALIM)=EXP(ELIM)*TOL ARE INTERVALS NEAR
UNDERFLOW&&OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.
RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LA>=Z.
DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).
*/
K1 = imach[15]
K2 = imach[16]
R1M5 = dmach[5]
K = min0(iabs(K1), iabs(K2))
ELIM = 2.303E0 * (float64(K)*R1M5 - 3.0E0)
K1 = imach[14] - 1
AA = R1M5 * float64(K1)
DIG = dmin(AA, 18.0E0)
AA = AA * 2.303E0
ALIM = ELIM + dmax(-AA, -41.45E0)
RL = 1.2E0*DIG + 3.0E0
ALAZ = dlog(AZ)
// TEST FOR PROPER RANGE.
AA = 0.5E0 / TOL
BB = float64(float32(imach[9])) * 0.5E0
AA = dmin(AA, BB)
AA = math.Pow(AA, TTH)
if AZ > AA {
goto TwoSixty
}
AA = dsqrt(AA)
if AZ > AA {
IERR = 3
}
tmp = zsqrt(complex(ZR, ZI))
CSQR = real(tmp)
CSQI = imag(tmp)
ZTAR = TTH * (ZR*CSQR - ZI*CSQI)
ZTAI = TTH * (ZR*CSQI + ZI*CSQR)
// RE(ZTA)<=0 WHEN RE(Z)<0, ESPECIALLY WHEN IM(Z) IS SMALL.
IFLAG = 0
SFAC = 1.0E0
AK = ZTAI
if ZR >= 0.0E0 {
goto Eighty
}
BK = ZTAR
CK = -dabs(BK)
ZTAR = CK
ZTAI = AK
Eighty:
if ZI != 0.0E0 {
goto Ninety
}
if ZR > 0.0E0 {
goto Ninety
}
ZTAR = 0.0E0
ZTAI = AK
Ninety:
AA = ZTAR
if AA >= 0.0E0 && ZR > 0.0E0 {
goto OneTen
}
if KODE == 2 {
goto OneHundred
}
// OVERFLOW TEST.
if AA > (-ALIM) {
goto OneHundred
}
AA = -AA + 0.25E0*ALAZ
IFLAG = 1
SFAC = TOL
if AA > ELIM {
goto TwoSeventy
}
OneHundred:
// CBKNU AND CACON return EXP(ZTA)*K(FNU,ZTA) ON KODE=2.
MR = 1
if ZI < 0.0E0 {
MR = -1
}
ZTAR, ZTAI, FNU, KODE, MR, _, CYR, CYI, NN, RL, TOL, ELIM, ALIM = zacaiOrig(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, NN, RL, TOL, ELIM, ALIM)
if NN < 0 {
goto TwoEighty
}
NZ = NZ + NN
goto OneThirty
OneTen:
if KODE == 2 {
goto OneTwenty
}
// UNDERFLOW TEST.
if AA < ALIM {
goto OneTwenty
}
AA = -AA - 0.25E0*ALAZ
IFLAG = 2
SFAC = 1.0E0 / TOL
if AA < (-ELIM) {
goto TwoTen
}
OneTwenty:
ZTAR, ZTAI, FNU, KODE, _, CYR, CYI, NZ, TOL, ELIM, ALIM = zbknuOrig(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, NZ, TOL, ELIM, ALIM)
OneThirty:
S1R = CYR[1] * COEF
S1I = CYI[1] * COEF
if IFLAG != 0 {
goto OneFifty
}
if ID == 1 {
goto OneFourty
}
AIR = CSQR*S1R - CSQI*S1I
AII = CSQR*S1I + CSQI*S1R
return
OneFourty:
AIR = -(ZR*S1R - ZI*S1I)
AII = -(ZR*S1I + ZI*S1R)
return
OneFifty:
S1R = S1R * SFAC
S1I = S1I * SFAC
if ID == 1 {
goto OneSixty
}
STR = S1R*CSQR - S1I*CSQI
S1I = S1R*CSQI + S1I*CSQR
S1R = STR
AIR = S1R / SFAC
AII = S1I / SFAC
return
OneSixty:
STR = -(S1R*ZR - S1I*ZI)
S1I = -(S1R*ZI + S1I*ZR)
S1R = STR
AIR = S1R / SFAC
AII = S1I / SFAC
return
OneSeventy:
AA = 1.0E+3 * dmach[1]
S1R = ZEROR
S1I = ZEROI
if ID == 1 {
goto OneNinety
}
if AZ <= AA {
goto OneEighty
}
S1R = C2 * ZR
S1I = C2 * ZI
OneEighty:
AIR = C1 - S1R
AII = -S1I
return
OneNinety:
AIR = -C2
AII = 0.0E0
AA = dsqrt(AA)
if AZ <= AA {
goto TwoHundred
}
S1R = 0.5E0 * (ZR*ZR - ZI*ZI)
S1I = ZR * ZI
TwoHundred:
AIR = AIR + C1*S1R
AII = AII + C1*S1I
return
TwoTen:
NZ = 1
AIR = ZEROR
AII = ZEROI
return
TwoSeventy:
NZ = 0
IERR = 2
return
TwoEighty:
if NN == (-1) {
goto TwoSeventy
}
NZ = 0
IERR = 5
return
TwoSixty:
IERR = 4
NZ = 0
return
}
// sbknu computes the k bessel function in the right half z plane.
func zbknuOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) (ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) {
/* Old dimension comment.
DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2),
* CYI(2)
*/
// TODO(btracey): Find which of these are inputs/outputs/both and clean up
// the function call.
// YR and YI have length n (but n+1 with better indexing)
var AA, AK, ASCLE, A1, A2, BB, BK, CAZ,
CBI, CBR, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER,
CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CTWOR,
CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ETEST, FC, FHS,
FI, FK, FKS, FMUI, FMUR, FPI, FR, G1, G2, HPI, PI, PR, PTI,
PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI,
RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM,
TTH, T1, T2, ELM, CELMR, ZDR, ZDI, AS, ALAS, HELIM float64
var I, IFLAG, INU, K, KFLAG, KK, KMAX, KODED, IDUM, J, IC, INUB, NW int
var tmp complex128
var CSSR, CSRR, BRY [4]float64
var CYR, CYI [3]float64
KMAX = 30
CZEROR = 0
CZEROI = 0
CONER = 1
CONEI = 0
CTWOR = 2
R1 = 2
DPI = 3.14159265358979324E0
RTHPI = 1.25331413731550025E0
SPI = 1.90985931710274403E0
HPI = 1.57079632679489662E0
FPI = 1.89769999331517738E0
TTH = 6.66666666666666666E-01
CC := [9]float64{math.NaN(), 5.77215664901532861E-01, -4.20026350340952355E-02,
-4.21977345555443367E-02, 7.21894324666309954E-03,
-2.15241674114950973E-04, -2.01348547807882387E-05,
1.13302723198169588E-06, 6.11609510448141582E-09}
CAZ = zabs(complex(ZR, ZI))
CSCLR = 1.0E0 / TOL
CRSCR = TOL
CSSR[1] = CSCLR
CSSR[2] = 1.0E0
CSSR[3] = CRSCR
CSRR[1] = CRSCR
CSRR[2] = 1.0E0
CSRR[3] = CSCLR
BRY[1] = 1.0E+3 * dmach[1] / TOL
BRY[2] = 1.0E0 / BRY[1]
BRY[3] = dmach[2]
NZ = 0
IFLAG = 0
KODED = KODE
RCAZ = 1.0E0 / CAZ
STR = ZR * RCAZ
STI = -ZI * RCAZ
RZR = (STR + STR) * RCAZ
RZI = (STI + STI) * RCAZ
INU = int(float32(FNU + 0.5))
DNU = FNU - float64(INU)
if dabs(DNU) == 0.5E0 {
goto OneTen
}
DNU2 = 0.0E0
if dabs(DNU) > TOL {
DNU2 = DNU * DNU
}
if CAZ > R1 {
goto OneTen
}
// SERIES FOR CABS(Z)<=R1.
FC = 1.0E0
tmp = zlog(complex(RZR, RZI))
SMUR = real(tmp)
SMUI = imag(tmp)
FMUR = SMUR * DNU
FMUI = SMUI * DNU
FMUR, FMUI, CSHR, CSHI, CCHR, CCHI = zshchOrig(FMUR, FMUI, CSHR, CSHI, CCHR, CCHI)
if DNU == 0.0E0 {
goto Ten
}
FC = DNU * DPI
FC = FC / dsin(FC)
SMUR = CSHR / DNU
SMUI = CSHI / DNU
Ten:
A2 = 1.0E0 + DNU
// GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU).
T2 = dexp(-dgamln(A2, IDUM))
T1 = 1.0E0 / (T2 * FC)
if dabs(DNU) > 0.1E0 {
goto Forty
}
// SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU).
AK = 1.0E0
S = CC[1]
for K = 2; K <= 8; K++ {
AK = AK * DNU2
TM = CC[K] * AK
S = S + TM
if dabs(TM) < TOL {
goto Thirty
}
}
Thirty:
G1 = -S
goto Fifty
Forty:
G1 = (T1 - T2) / (DNU + DNU)
Fifty:
G2 = (T1 + T2) * 0.5E0
FR = FC * (CCHR*G1 + SMUR*G2)
FI = FC * (CCHI*G1 + SMUI*G2)
tmp = zexp(complex(FMUR, FMUI))
STR = real(tmp)
STI = imag(tmp)
PR = 0.5E0 * STR / T2
PI = 0.5E0 * STI / T2
tmp = zdiv(complex(0.5, 0), complex(STR, STI))
PTR = real(tmp)
PTI = imag(tmp)
QR = PTR / T1
QI = PTI / T1
S1R = FR
S1I = FI
S2R = PR
S2I = PI
AK = 1.0E0
A1 = 1.0E0
CKR = CONER
CKI = CONEI
BK = 1.0E0 - DNU2
if INU > 0 || N > 1 {
goto Eighty
}
// GENERATE K(FNU,Z), 0.0E0 <= FNU < 0.5E0 AND N=1.
if CAZ < TOL {
goto Seventy
}
tmp = zmlt(complex(ZR, ZI), complex(ZR, ZI))
CZR = real(tmp)
CZI = imag(tmp)
CZR = 0.25E0 * CZR
CZI = 0.25E0 * CZI
T1 = 0.25E0 * CAZ * CAZ
Sixty:
FR = (FR*AK + PR + QR) / BK
FI = (FI*AK + PI + QI) / BK
STR = 1.0E0 / (AK - DNU)
PR = PR * STR
PI = PI * STR
STR = 1.0E0 / (AK + DNU)
QR = QR * STR
QI = QI * STR
STR = CKR*CZR - CKI*CZI
RAK = 1.0E0 / AK
CKI = (CKR*CZI + CKI*CZR) * RAK
CKR = STR * RAK
S1R = CKR*FR - CKI*FI + S1R
S1I = CKR*FI + CKI*FR + S1I
A1 = A1 * T1 * RAK
BK = BK + AK + AK + 1.0E0
AK = AK + 1.0E0
if A1 > TOL {
goto Sixty
}
Seventy:
YR[1] = S1R
YI[1] = S1I
if KODED == 1 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
tmp = zexp(complex(ZR, ZI))
STR = real(tmp)
STI = imag(tmp)
tmp = zmlt(complex(S1R, S1I), complex(STR, STI))
YR[1] = real(tmp)
YI[1] = imag(tmp)
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
// GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE.
Eighty:
if CAZ < TOL {
goto OneHundred
}
tmp = zmlt(complex(ZR, ZI), complex(ZR, ZI))
CZR = real(tmp)
CZI = imag(tmp)
CZR = 0.25E0 * CZR
CZI = 0.25E0 * CZI
T1 = 0.25E0 * CAZ * CAZ
Ninety:
FR = (FR*AK + PR + QR) / BK
FI = (FI*AK + PI + QI) / BK
STR = 1.0E0 / (AK - DNU)
PR = PR * STR
PI = PI * STR
STR = 1.0E0 / (AK + DNU)
QR = QR * STR
QI = QI * STR
STR = CKR*CZR - CKI*CZI
RAK = 1.0E0 / AK
CKI = (CKR*CZI + CKI*CZR) * RAK
CKR = STR * RAK
S1R = CKR*FR - CKI*FI + S1R
S1I = CKR*FI + CKI*FR + S1I
STR = PR - FR*AK
STI = PI - FI*AK
S2R = CKR*STR - CKI*STI + S2R
S2I = CKR*STI + CKI*STR + S2I
A1 = A1 * T1 * RAK
BK = BK + AK + AK + 1.0E0
AK = AK + 1.0E0
if A1 > TOL {
goto Ninety
}
OneHundred:
KFLAG = 2
A1 = FNU + 1.0E0
AK = A1 * dabs(SMUR)
if AK > ALIM {
KFLAG = 3
}
STR = CSSR[KFLAG]
P2R = S2R * STR
P2I = S2I * STR
tmp = zmlt(complex(P2R, P2I), complex(RZR, RZI))
S2R = real(tmp)
S2I = imag(tmp)
S1R = S1R * STR
S1I = S1I * STR
if KODED == 1 {
goto TwoTen
}
tmp = zexp(complex(ZR, ZI))
FR = real(tmp)
FI = imag(tmp)
tmp = zmlt(complex(S1R, S1I), complex(FR, FI))
S1R = real(tmp)
S1I = imag(tmp)
tmp = zmlt(complex(S2R, S2I), complex(FR, FI))
S2R = real(tmp)
S2I = imag(tmp)
goto TwoTen
// IFLAG=0 MEANS NO UNDERFLOW OCCURRED
// IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH
// KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD RECURSION
OneTen:
tmp = zsqrt(complex(ZR, ZI))
STR = real(tmp)
STI = imag(tmp)
tmp = zdiv(complex(RTHPI, CZEROI), complex(STR, STI))
COEFR = real(tmp)
COEFI = imag(tmp)
KFLAG = 2
if KODED == 2 {
goto OneTwenty
}
if ZR > ALIM {
goto TwoNinety
}
STR = dexp(-ZR) * CSSR[KFLAG]
STI = -STR * dsin(ZI)
STR = STR * dcos(ZI)
tmp = zmlt(complex(COEFR, COEFI), complex(STR, STI))
COEFR = real(tmp)
COEFI = imag(tmp)
OneTwenty:
if dabs(DNU) == 0.5E0 {
goto ThreeHundred
}
// MILLER ALGORITHM FOR CABS(Z)>R1.
AK = dcos(DPI * DNU)
AK = dabs(AK)
if AK == CZEROR {
goto ThreeHundred
}
FHS = dabs(0.25E0 - DNU2)
if FHS == CZEROR {
goto ThreeHundred
}
// COMPUTE R2=F(E). if CABS(Z)>=R2, USE FORWARD RECURRENCE TO
// DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON
// 12<=E<=60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))=
// TOL WHERE B IS THE BASE OF THE ARITHMETIC.
T1 = float64(imach[14] - 1)
T1 = T1 * dmach[5] * 3.321928094E0
T1 = dmax(T1, 12.0E0)
T1 = dmin(T1, 60.0E0)
T2 = TTH*T1 - 6.0E0
if ZR != 0.0E0 {
goto OneThirty
}
T1 = HPI
goto OneFourty
OneThirty:
T1 = datan(ZI / ZR)
T1 = dabs(T1)
OneFourty:
if T2 > CAZ {
goto OneSeventy
}
// FORWARD RECURRENCE LOOP WHEN CABS(Z)>=R2.
ETEST = AK / (DPI * CAZ * TOL)
FK = CONER
if ETEST < CONER {
goto OneEighty
}
FKS = CTWOR
CKR = CAZ + CAZ + CTWOR
P1R = CZEROR
P2R = CONER
for I = 1; I <= KMAX; I++ {
AK = FHS / FKS
CBR = CKR / (FK + CONER)
PTR = P2R
P2R = CBR*P2R - P1R*AK
P1R = PTR
CKR = CKR + CTWOR
FKS = FKS + FK + FK + CTWOR
FHS = FHS + FK + FK
FK = FK + CONER
STR = dabs(P2R) * FK
if ETEST < STR {
goto OneSixty
}
}
goto ThreeTen
OneSixty:
FK = FK + SPI*T1*dsqrt(T2/CAZ)
FHS = dabs(0.25 - DNU2)
goto OneEighty
OneSeventy:
// COMPUTE BACKWARD INDEX K FOR CABS(Z)<R2.
A2 = dsqrt(CAZ)
AK = FPI * AK / (TOL * dsqrt(A2))
AA = 3.0E0 * T1 / (1.0E0 + CAZ)
BB = 14.7E0 * T1 / (28.0E0 + CAZ)
AK = (dlog(AK) + CAZ*dcos(AA)/(1.0E0+0.008E0*CAZ)) / dcos(BB)
FK = 0.12125E0*AK*AK/CAZ + 1.5E0
OneEighty:
// BACKWARD RECURRENCE LOOP FOR MILLER ALGORITHM.
K = int(float32(FK))
FK = float64(K)
FKS = FK * FK
P1R = CZEROR
P1I = CZEROI
P2R = TOL
P2I = CZEROI
CSR = P2R
CSI = P2I
for I = 1; I <= K; I++ {
A1 = FKS - FK
AK = (FKS + FK) / (A1 + FHS)
RAK = 2.0E0 / (FK + CONER)
CBR = (FK + ZR) * RAK
CBI = ZI * RAK
PTR = P2R
PTI = P2I
P2R = (PTR*CBR - PTI*CBI - P1R) * AK
P2I = (PTI*CBR + PTR*CBI - P1I) * AK
P1R = PTR
P1I = PTI
CSR = CSR + P2R
CSI = CSI + P2I
FKS = A1 - FK + CONER
FK = FK - CONER
}
// COMPUTE (P2/CS)=(P2/CABS(CS))*(CONJG(CS)/CABS(CS)) FOR BETTER SCALING.
TM = zabs(complex(CSR, CSI))
PTR = 1.0E0 / TM
S1R = P2R * PTR
S1I = P2I * PTR
CSR = CSR * PTR
CSI = -CSI * PTR
tmp = zmlt(complex(COEFR, COEFI), complex(S1R, S1I))
STR = real(tmp)
STI = imag(tmp)
tmp = zmlt(complex(STR, STI), complex(CSR, CSI))
S1R = real(tmp)
S1I = imag(tmp)
if INU > 0 || N > 1 {
goto TwoHundred
}
ZDR = ZR
ZDI = ZI
if IFLAG == 1 {
goto TwoSeventy
}
goto TwoFourty
TwoHundred:
// COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING.
TM = zabs(complex(P2R, P2I))
PTR = 1.0E0 / TM
P1R = P1R * PTR
P1I = P1I * PTR
P2R = P2R * PTR
P2I = -P2I * PTR
tmp = zmlt(complex(P1R, P1I), complex(P2R, P2I))
PTR = real(tmp)
PTI = imag(tmp)
STR = DNU + 0.5E0 - PTR
STI = -PTI
tmp = zdiv(complex(STR, STI), complex(ZR, ZI))
STR = real(tmp)
STI = imag(tmp)
STR = STR + 1.0E0
tmp = zmlt(complex(STR, STI), complex(S1R, S1I))
S2R = real(tmp)
S2I = imag(tmp)
// FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH
// SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3
TwoTen:
STR = DNU + 1.0E0
CKR = STR * RZR
CKI = STR * RZI
if N == 1 {
INU = INU - 1
}
if INU > 0 {
goto TwoTwenty
}
if N > 1 {
goto TwoFifteen
}
S1R = S2R
S1I = S2I
TwoFifteen:
ZDR = ZR
ZDI = ZI
if IFLAG == 1 {
goto TwoSeventy
}
goto TwoFourty
TwoTwenty:
INUB = 1
if IFLAG == 1 {
goto TwoSixtyOne
}
TwoTwentyFive:
P1R = CSRR[KFLAG]
ASCLE = BRY[KFLAG]
for I = INUB; I <= INU; I++ {
STR = S2R
STI = S2I
S2R = CKR*STR - CKI*STI + S1R
S2I = CKR*STI + CKI*STR + S1I
S1R = STR
S1I = STI
CKR = CKR + RZR
CKI = CKI + RZI
if KFLAG >= 3 {
continue
}
P2R = S2R * P1R
P2I = S2I * P1R
STR = dabs(P2R)
STI = dabs(P2I)
P2M = dmax(STR, STI)
if P2M <= ASCLE {
continue
}
KFLAG = KFLAG + 1
ASCLE = BRY[KFLAG]
S1R = S1R * P1R
S1I = S1I * P1R
S2R = P2R
S2I = P2I
STR = CSSR[KFLAG]
S1R = S1R * STR
S1I = S1I * STR
S2R = S2R * STR
S2I = S2I * STR
P1R = CSRR[KFLAG]
}
if N != 1 {
goto TwoFourty
}
S1R = S2R
S1I = S2I
TwoFourty:
STR = CSRR[KFLAG]
YR[1] = S1R * STR
YI[1] = S1I * STR
if N == 1 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
YR[2] = S2R * STR
YI[2] = S2I * STR
if N == 2 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
KK = 2
TwoFifty:
KK = KK + 1
if KK > N {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
P1R = CSRR[KFLAG]
ASCLE = BRY[KFLAG]
for I = KK; I <= N; I++ {
P2R = S2R
P2I = S2I
S2R = CKR*P2R - CKI*P2I + S1R
S2I = CKI*P2R + CKR*P2I + S1I
S1R = P2R
S1I = P2I
CKR = CKR + RZR
CKI = CKI + RZI
P2R = S2R * P1R
P2I = S2I * P1R
YR[I] = P2R
YI[I] = P2I
if KFLAG >= 3 {
continue
}
STR = dabs(P2R)
STI = dabs(P2I)
P2M = dmax(STR, STI)
if P2M <= ASCLE {
continue
}
KFLAG = KFLAG + 1
ASCLE = BRY[KFLAG]
S1R = S1R * P1R
S1I = S1I * P1R
S2R = P2R
S2I = P2I
STR = CSSR[KFLAG]
S1R = S1R * STR
S1I = S1I * STR
S2R = S2R * STR
S2I = S2I * STR
P1R = CSRR[KFLAG]
}
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
// IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW.
TwoSixtyOne:
HELIM = 0.5E0 * ELIM
ELM = dexp(-ELIM)
CELMR = ELM
ASCLE = BRY[1]
ZDR = ZR
ZDI = ZI
IC = -1
J = 2
for I = 1; I <= INU; I++ {
STR = S2R
STI = S2I
S2R = STR*CKR - STI*CKI + S1R
S2I = STI*CKR + STR*CKI + S1I
S1R = STR
S1I = STI
CKR = CKR + RZR
CKI = CKI + RZI
AS = zabs(complex(S2R, S2I))
ALAS = dlog(AS)
P2R = -ZDR + ALAS
if P2R < (-ELIM) {
goto TwoSixtyThree
}
tmp = zlog(complex(S2R, S2I))
STR = real(tmp)
STI = imag(tmp)
P2R = -ZDR + STR
P2I = -ZDI + STI
P2M = dexp(P2R) / TOL
P1R = P2M * dcos(P2I)
P1I = P2M * dsin(P2I)
P1R, P1I, NW, ASCLE, TOL = zuchkOrig(P1R, P1I, NW, ASCLE, TOL)
if NW != 0 {
goto TwoSixtyThree
}
J = 3 - J
CYR[J] = P1R
CYI[J] = P1I
if IC == (I - 1) {
goto TwoSixtyFour
}
IC = I
continue
TwoSixtyThree:
if ALAS < HELIM {
continue
}
ZDR = ZDR - ELIM
S1R = S1R * CELMR
S1I = S1I * CELMR
S2R = S2R * CELMR
S2I = S2I * CELMR
}
if N != 1 {
goto TwoSeventy
}
S1R = S2R
S1I = S2I
goto TwoSeventy
TwoSixtyFour:
KFLAG = 1
INUB = I + 1
S2R = CYR[J]
S2I = CYI[J]
J = 3 - J
S1R = CYR[J]
S1I = CYI[J]
if INUB <= INU {
goto TwoTwentyFive
}
if N != 1 {
goto TwoFourty
}
S1R = S2R
S1I = S2I
goto TwoFourty
TwoSeventy:
YR[1] = S1R
YI[1] = S1I
if N == 1 {
goto TwoEighty
}
YR[2] = S2R
YI[2] = S2I
TwoEighty:
ASCLE = BRY[1]
ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM = zksclOrig(ZDR, ZDI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM)
INU = N - NZ
if INU <= 0 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
KK = NZ + 1
S1R = YR[KK]
S1I = YI[KK]
YR[KK] = S1R * CSRR[1]
YI[KK] = S1I * CSRR[1]
if INU == 1 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
KK = NZ + 2
S2R = YR[KK]
S2I = YI[KK]
YR[KK] = S2R * CSRR[1]
YI[KK] = S2I * CSRR[1]
if INU == 2 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
T2 = FNU + float64(float32(KK-1))
CKR = T2 * RZR
CKI = T2 * RZI
KFLAG = 1
goto TwoFifty
TwoNinety:
// SCALE BY dexp(Z), IFLAG = 1 CASES.
KODED = 2
IFLAG = 1
KFLAG = 2
goto OneTwenty
// FNU=HALF ODD INTEGER CASE, DNU=-0.5
ThreeHundred:
S1R = COEFR
S1I = COEFI
S2R = COEFR
S2I = COEFI
goto TwoTen
ThreeTen:
NZ = -2
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
// SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE
// ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN
// return WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL.
func zksclOrig(ZRR, ZRI, FNU float64, N int, YR, YI []float64, NZ int, RZR, RZI, ASCLE, TOL, ELIM float64) (
ZRRout, ZRIout, FNUout float64, Nout int, YRout, YIout []float64, NZout int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) {
var ACS, AS, CKI, CKR, CSI, CSR, FN, STR, S1I, S1R, S2I,
S2R, ZEROI, ZEROR, ZDR, ZDI, CELMR, ELM, HELIM, ALAS float64
var I, IC, KK, NN, NW int
var tmp complex128
var CYR, CYI [3]float64
// DIMENSION YR(N), YI(N), CYR(2), CYI(2)
ZEROR = 0
ZEROI = 0
NZ = 0
IC = 0
NN = min0(2, N)
for I = 1; I <= NN; I++ {
S1R = YR[I]
S1I = YI[I]
CYR[I] = S1R
CYI[I] = S1I
AS = zabs(complex(S1R, S1I))
ACS = -ZRR + dlog(AS)
NZ = NZ + 1
YR[I] = ZEROR
YI[I] = ZEROI
if ACS < (-ELIM) {
continue
}
tmp = zlog(complex(S1R, S1I))
CSR = real(tmp)
CSI = imag(tmp)
CSR = CSR - ZRR
CSI = CSI - ZRI
STR = dexp(CSR) / TOL
CSR = STR * dcos(CSI)
CSI = STR * dsin(CSI)
CSR, CSI, NW, ASCLE, TOL = zuchkOrig(CSR, CSI, NW, ASCLE, TOL)
if NW != 0 {
continue
}
YR[I] = CSR
YI[I] = CSI
IC = I
NZ = NZ - 1
}
if N == 1 {
return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM
}
if IC > 1 {
goto Twenty
}
YR[1] = ZEROR
YI[1] = ZEROI
NZ = 2
Twenty:
if N == 2 {
return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM
}
if NZ == 0 {
return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM
}
FN = FNU + 1.0E0
CKR = FN * RZR
CKI = FN * RZI
S1R = CYR[1]
S1I = CYI[1]
S2R = CYR[2]
S2I = CYI[2]
HELIM = 0.5E0 * ELIM
ELM = dexp(-ELIM)
CELMR = ELM
ZDR = ZRR
ZDI = ZRI
// FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF
// S2 GETS LARGER THAN EXP(ELIM/2)
for I = 3; I <= N; I++ {
KK = I
CSR = S2R
CSI = S2I
S2R = CKR*CSR - CKI*CSI + S1R
S2I = CKI*CSR + CKR*CSI + S1I
S1R = CSR
S1I = CSI
CKR = CKR + RZR
CKI = CKI + RZI
AS = zabs(complex(S2R, S2I))
ALAS = dlog(AS)
ACS = -ZDR + ALAS
NZ = NZ + 1
YR[I] = ZEROR
YI[I] = ZEROI
if ACS < (-ELIM) {
goto TwentyFive
}
tmp = zlog(complex(S2R, S2I))
CSR = real(tmp)
CSI = imag(tmp)
CSR = CSR - ZDR
CSI = CSI - ZDI
STR = dexp(CSR) / TOL
CSR = STR * dcos(CSI)
CSI = STR * dsin(CSI)
CSR, CSI, NW, ASCLE, TOL = zuchkOrig(CSR, CSI, NW, ASCLE, TOL)
if NW != 0 {
goto TwentyFive
}
YR[I] = CSR
YI[I] = CSI
NZ = NZ - 1
if IC == KK-1 {
goto Forty
}
IC = KK
continue
TwentyFive:
if ALAS < HELIM {
continue
}
ZDR = ZDR - ELIM
S1R = S1R * CELMR
S1I = S1I * CELMR
S2R = S2R * CELMR
S2I = S2I * CELMR
}
NZ = N
if IC == N {
NZ = N - 1
}
goto FourtyFive
Forty:
NZ = KK - 2
FourtyFive:
for I = 1; I <= NZ; I++ {
YR[I] = ZEROR
YI[I] = ZEROI
}
return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM
}
// Y ENTERS AS A SCALED QUANTITY WHOSE MAGNITUDE IS GREATER THAN
// EXP(-ALIM)=ASCLE=1.0E+3*dmach[1)/TOL. THE TEST IS MADE TO SEE
// if THE MAGNITUDE OF THE REAL OR IMAGINARY PART WOULD UNDERFLOW
// WHEN Y IS SCALED (BY TOL) TO ITS PROPER VALUE. Y IS ACCEPTED
// if THE UNDERFLOW IS AT LEAST ONE PRECISION BELOW THE MAGNITUDE
// OF THE LARGEST COMPONENT; OTHERWISE THE PHASE ANGLE DOES NOT HAVE
// ABSOLUTE ACCURACY AND AN UNDERFLOW IS ASSUMED.
func zuchkOrig(YR, YI float64, NZ int, ASCLE, TOL float64) (YRout, YIout float64, NZout int, ASCLEout, TOLout float64) {
var SS, ST, WR, WI float64
NZ = 0
WR = dabs(YR)
WI = dabs(YI)
ST = dmin(WR, WI)
if ST > ASCLE {
return YR, YI, NZ, ASCLE, TOL
}
SS = dmax(WR, WI)
ST = ST / TOL
if SS < ST {
NZ = 1
}
return YR, YI, NZ, ASCLE, TOL
}
// ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA
//
// K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN)
// MP=PI*MR*CMPLX(0.0,1.0)
//
// TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT
// HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1.
// ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND
// RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT if ZACON
// IS CALLED FROM ZAIRY.
func zacaiOrig(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) (
ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) {
var ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR,
CSPNI, C1R, C1I, C2R, C2I, DFNU, FMR, PI,
SGN, YY, ZNR, ZNI float64
var INU, IUF, NN, NW int
CYR := []float64{math.NaN(), 0, 0}
CYI := []float64{math.NaN(), 0, 0}
PI = math.Pi
NZ = 0
ZNR = -ZR
ZNI = -ZI
AZ = zabs(complex(ZR, ZI))
NN = N
DFNU = FNU + float64(float32(N-1))
if AZ <= 2.0E0 {
goto Ten
}
if AZ*AZ*0.25 > DFNU+1.0E0 {
goto Twenty
}
Ten:
// POWER SERIES FOR THE I FUNCTION.
ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM = zseriOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL, ELIM, ALIM)
goto Forty
Twenty:
if AZ < RL {
goto Thirty
}
// ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION.
ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM = zasyiOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, RL, TOL, ELIM, ALIM)
if NW < 0 {
goto Eighty
}
goto Forty
Thirty:
// MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION
ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL = zmlriOrig(ZNR, ZNI, FNU, KODE, NN, YR, YI, NW, TOL)
if NW < 0 {
goto Eighty
}
Forty:
// ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION.
ZNR, ZNI, FNU, KODE, _, CYR, CYI, NW, TOL, ELIM, ALIM = zbknuOrig(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, NW, TOL, ELIM, ALIM)
if NW != 0 {
goto Eighty
}
FMR = float64(float32(MR))
SGN = -math.Copysign(PI, FMR)
CSGNR = 0.0E0
CSGNI = SGN
if KODE == 1 {
goto Fifty
}
YY = -ZNI
CSGNR = -CSGNI * dsin(YY)
CSGNI = CSGNI * dcos(YY)
Fifty:
// CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE
// WHEN FNU IS LARGE
INU = int(float32(FNU))
ARG = (FNU - float64(float32(INU))) * SGN
CSPNR = dcos(ARG)
CSPNI = dsin(ARG)
if INU%2 == 0 {
goto Sixty
}
CSPNR = -CSPNR
CSPNI = -CSPNI
Sixty:
C1R = CYR[1]
C1I = CYI[1]
C2R = YR[1]
C2I = YI[1]
if KODE == 1 {
goto Seventy
}
IUF = 0
ASCLE = 1.0E+3 * dmach[1] / TOL
ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF = zs1s2Orig(ZNR, ZNI, C1R, C1I, C2R, C2I, NW, ASCLE, ALIM, IUF)
NZ = NZ + NW
Seventy:
YR[1] = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I
YI[1] = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R
return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
Eighty:
NZ = -1
if NW == -2 {
NZ = -2
}
return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
}
// ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY
// MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE
// REGION CABS(Z)>MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL return.
// NZ<0 INDICATES AN OVERFLOW ON KODE=1.
func zasyiOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, RL, TOL, ELIM, ALIM float64) (
ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, RLout, TOLout, ELIMout, ALIMout float64) {
var AA, AEZ, AK, AK1I, AK1R, ARG, ARM, ATOL,
AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI,
CZR, DFNU, DKI, DKR, DNU2, EZI, EZR, FDN, PI, P1I,
P1R, RAZ, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I,
S2R, TZI, TZR, ZEROI, ZEROR float64
var I, IB, IL, INU, J, JL, K, KODED, M, NN int
var tmp complex128
PI = math.Pi
RTPI = 0.159154943091895336E0
ZEROR = 0
ZEROI = 0
CONER = 1
CONEI = 0
NZ = 0
AZ = zabs(complex(ZR, ZI))
ARM = 1.0E3 * dmach[1]
RTR1 = dsqrt(ARM)
IL = min0(2, N)
DFNU = FNU + float64(float32(N-IL))
// OVERFLOW TEST
RAZ = 1.0E0 / AZ
STR = ZR * RAZ
STI = -ZI * RAZ
AK1R = RTPI * STR * RAZ
AK1I = RTPI * STI * RAZ
tmp = zsqrt(complex(AK1R, AK1I))
AK1R = real(tmp)
AK1I = imag(tmp)
CZR = ZR
CZI = ZI
if KODE != 2 {
goto Ten
}
CZR = ZEROR
CZI = ZI
Ten:
if dabs(CZR) > ELIM {
goto OneHundred
}
DNU2 = DFNU + DFNU
KODED = 1
if (dabs(CZR) > ALIM) && (N > 2) {
goto Twenty
}
KODED = 0
tmp = zexp(complex(CZR, CZI))
STR = real(tmp)
STI = imag(tmp)
tmp = zmlt(complex(AK1R, AK1I), complex(STR, STI))
AK1R = real(tmp)
AK1I = imag(tmp)
Twenty:
FDN = 0.0E0
if DNU2 > RTR1 {
FDN = DNU2 * DNU2
}
EZR = ZR * 8.0E0
EZI = ZI * 8.0E0
// WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE
// FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE
// EXPANSION FOR THE IMAGINARY PART.
AEZ = 8.0E0 * AZ
S = TOL / AEZ
JL = int(float32(RL+RL)) + 2
P1R = ZEROR
P1I = ZEROI
if ZI == 0.0E0 {
goto Thirty
}
// CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF
// SIGNIFICANCE WHEN FNU OR N IS LARGE
INU = int(float32(FNU))
ARG = (FNU - float64(float32(INU))) * PI
INU = INU + N - IL
AK = -dsin(ARG)
BK = dcos(ARG)
if ZI < 0.0E0 {
BK = -BK
}
P1R = AK
P1I = BK
if INU%2 == 0 {
goto Thirty
}
P1R = -P1R
P1I = -P1I
Thirty:
for K = 1; K <= IL; K++ {
SQK = FDN - 1.0E0
ATOL = S * dabs(SQK)
SGN = 1.0E0
CS1R = CONER
CS1I = CONEI
CS2R = CONER
CS2I = CONEI
CKR = CONER
CKI = CONEI
AK = 0.0E0
AA = 1.0E0
BB = AEZ
DKR = EZR
DKI = EZI
// TODO(btracey): This loop is executed tens of thousands of times. Why?
// is that really necessary?
for J = 1; J <= JL; J++ {
tmp = zdiv(complex(CKR, CKI), complex(DKR, DKI))
STR = real(tmp)
STI = imag(tmp)
CKR = STR * SQK
CKI = STI * SQK
CS2R = CS2R + CKR
CS2I = CS2I + CKI
SGN = -SGN
CS1R = CS1R + CKR*SGN
CS1I = CS1I + CKI*SGN
DKR = DKR + EZR
DKI = DKI + EZI
AA = AA * dabs(SQK) / BB
BB = BB + AEZ
AK = AK + 8.0E0
SQK = SQK - AK
if AA <= ATOL {
goto Fifty
}
}
goto OneTen
Fifty:
S2R = CS1R
S2I = CS1I
if ZR+ZR >= ELIM {
goto Sixty
}
TZR = ZR + ZR
TZI = ZI + ZI
tmp = zexp(complex(-TZR, -TZI))
STR = real(tmp)
STI = imag(tmp)
tmp = zmlt(complex(STR, STI), complex(P1R, P1I))
STR = real(tmp)
STI = imag(tmp)
tmp = zmlt(complex(STR, STI), complex(CS2R, CS2I))
STR = real(tmp)
STI = imag(tmp)
S2R = S2R + STR
S2I = S2I + STI
Sixty:
FDN = FDN + 8.0E0*DFNU + 4.0E0
P1R = -P1R
P1I = -P1I
M = N - IL + K
YR[M] = S2R*AK1R - S2I*AK1I
YI[M] = S2R*AK1I + S2I*AK1R
}
if N <= 2 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
}
NN = N
K = NN - 2
AK = float64(float32(K))
STR = ZR * RAZ
STI = -ZI * RAZ
RZR = (STR + STR) * RAZ
RZI = (STI + STI) * RAZ
IB = 3
for I = IB; I <= NN; I++ {
YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2]
YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2]
AK = AK - 1.0E0
K = K - 1
}
if KODED == 0 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
}
tmp = zexp(complex(CZR, CZI))
CKR = real(tmp)
CKI = imag(tmp)
for I = 1; I <= NN; I++ {
STR = YR[I]*CKR - YI[I]*CKI
YI[I] = YR[I]*CKI + YI[I]*CKR
YR[I] = STR
}
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
OneHundred:
NZ = -1
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
OneTen:
NZ = -2
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
}
// ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z)>=0.0 BY THE
// MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES.
func zmlriOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL float64) (
ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout float64) {
var ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI,
CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, PTI, PTR, P1I,
P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI,
SUMR, TFNF, TST, ZEROI, ZEROR float64
var I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, M int
var tmp complex128
ZEROR = 0
ZEROI = 0
CONER = 1
CONEI = 0
SCLE = dmach[1] / TOL
NZ = 0
AZ = zabs(complex(ZR, ZI))
IAZ = int(float32(AZ))
IFNU = int(float32(FNU))
INU = IFNU + N - 1
AT = float64(float32(IAZ)) + 1.0E0
RAZ = 1.0E0 / AZ
STR = ZR * RAZ
STI = -ZI * RAZ
CKR = STR * AT * RAZ
CKI = STI * AT * RAZ
RZR = (STR + STR) * RAZ
RZI = (STI + STI) * RAZ
P1R = ZEROR
P1I = ZEROI
P2R = CONER
P2I = CONEI
ACK = (AT + 1.0E0) * RAZ
RHO = ACK + dsqrt(ACK*ACK-1.0E0)
RHO2 = RHO * RHO
TST = (RHO2 + RHO2) / ((RHO2 - 1.0E0) * (RHO - 1.0E0))
TST = TST / TOL
// COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES.
//fmt.Println("before loop", P2R, P2I, CKR, CKI, RZR, RZI, TST, AK)
AK = AT
for I = 1; I <= 80; I++ {
PTR = P2R
PTI = P2I
P2R = P1R - (CKR*PTR - CKI*PTI)
P2I = P1I - (CKI*PTR + CKR*PTI)
P1R = PTR
P1I = PTI
CKR = CKR + RZR
CKI = CKI + RZI
AP = zabs(complex(P2R, P2I))
if AP > TST*AK*AK {
goto Twenty
}
AK = AK + 1.0E0
}
goto OneTen
Twenty:
I = I + 1
K = 0
if INU < IAZ {
goto Forty
}
// COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS.
P1R = ZEROR
P1I = ZEROI
P2R = CONER
P2I = CONEI
AT = float64(float32(INU)) + 1.0E0
STR = ZR * RAZ
STI = -ZI * RAZ
CKR = STR * AT * RAZ
CKI = STI * AT * RAZ
ACK = AT * RAZ
TST = dsqrt(ACK / TOL)
ITIME = 1
for K = 1; K <= 80; K++ {
PTR = P2R
PTI = P2I
P2R = P1R - (CKR*PTR - CKI*PTI)
P2I = P1I - (CKR*PTI + CKI*PTR)
P1R = PTR
P1I = PTI
CKR = CKR + RZR
CKI = CKI + RZI
AP = zabs(complex(P2R, P2I))
if AP < TST {
continue
}
if ITIME == 2 {
goto Forty
}
ACK = zabs(complex(CKR, CKI))
FLAM = ACK + dsqrt(ACK*ACK-1.0E0)
FKAP = AP / zabs(complex(P1R, P1I))
RHO = dmin(FLAM, FKAP)
TST = TST * dsqrt(RHO/(RHO*RHO-1.0E0))
ITIME = 2
}
goto OneTen
Forty:
// BACKWARD RECURRENCE AND SUM NORMALIZING RELATION.
K = K + 1
KK = max0(I+IAZ, K+INU)
FKK = float64(float32(KK))
P1R = ZEROR
P1I = ZEROI
// SCALE P2 AND SUM BY SCLE.
P2R = SCLE
P2I = ZEROI
FNF = FNU - float64(float32(IFNU))
TFNF = FNF + FNF
BK = dgamln(FKK+TFNF+1.0E0, IDUM) - dgamln(FKK+1.0E0, IDUM) - dgamln(TFNF+1.0E0, IDUM)
BK = dexp(BK)
SUMR = ZEROR
SUMI = ZEROI
KM = KK - INU
for I = 1; I <= KM; I++ {
PTR = P2R
PTI = P2I
P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)
P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI)
P1R = PTR
P1I = PTI
AK = 1.0E0 - TFNF/(FKK+TFNF)
ACK = BK * AK
SUMR = SUMR + (ACK+BK)*P1R
SUMI = SUMI + (ACK+BK)*P1I
BK = ACK
FKK = FKK - 1.0E0
}
YR[N] = P2R
YI[N] = P2I
if N == 1 {
goto Seventy
}
for I = 2; I <= N; I++ {
PTR = P2R
PTI = P2I
P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)
P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI)
P1R = PTR
P1I = PTI
AK = 1.0E0 - TFNF/(FKK+TFNF)
ACK = BK * AK
SUMR = SUMR + (ACK+BK)*P1R
SUMI = SUMI + (ACK+BK)*P1I
BK = ACK
FKK = FKK - 1.0E0
M = N - I + 1
YR[M] = P2R
YI[M] = P2I
}
Seventy:
if IFNU <= 0 {
goto Ninety
}
for I = 1; I <= IFNU; I++ {
PTR = P2R
PTI = P2I
P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)
P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR)
P1R = PTR
P1I = PTI
AK = 1.0E0 - TFNF/(FKK+TFNF)
ACK = BK * AK
SUMR = SUMR + (ACK+BK)*P1R
SUMI = SUMI + (ACK+BK)*P1I
BK = ACK
FKK = FKK - 1.0E0
}
Ninety:
PTR = ZR
PTI = ZI
if KODE == 2 {
PTR = ZEROR
}
tmp = zlog(complex(RZR, RZI))
STR = real(tmp)
STI = imag(tmp)
P1R = -FNF*STR + PTR
P1I = -FNF*STI + PTI
AP = dgamln(1.0E0+FNF, IDUM)
PTR = P1R - AP
PTI = P1I
// THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW
// IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES.
P2R = P2R + SUMR
P2I = P2I + SUMI
AP = zabs(complex(P2R, P2I))
P1R = 1.0E0 / AP
tmp = zexp(complex(PTR, PTI))
STR = real(tmp)
STI = imag(tmp)
CKR = STR * P1R
CKI = STI * P1R
PTR = P2R * P1R
PTI = -P2I * P1R
tmp = zmlt(complex(CKR, CKI), complex(PTR, PTI))
CNORMR = real(tmp)
CNORMI = imag(tmp)
for I = 1; I <= N; I++ {
STR = YR[I]*CNORMR - YI[I]*CNORMI
YI[I] = YR[I]*CNORMI + YI[I]*CNORMR
YR[I] = STR
}
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL
OneTen:
NZ = -2
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL
}
// ZSERI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY
// MEANS OF THE POWER SERIES FOR LARGE CABS(Z) IN THE
// REGION CABS(Z)<=2*SQRT(FNU+1). NZ=0 IS A NORMAL return.
// NZ>0 MEANS THAT THE LAST NZ COMPONENTS WERE SET TO ZERO
// DUE TO UNDERFLOW. NZ<0 MEANS UNDERFLOW OCCURRED, BUT THE
// CONDITION CABS(Z)<=2*SQRT(FNU+1) WAS VIOLATED AND THE
// COMPUTATION MUST BE COMPLETED IN ANOTHER ROUTINE WITH N=N-ABS(NZ).
func zseriOrig(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, NZ int, TOL, ELIM, ALIM float64) (
ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZout int, TOLout, ELIMout, ALIMout float64) {
var AA, ACZ, AK, AK1I, AK1R, ARM, ASCLE, ATOL,
AZ, CKI, CKR, COEFI, COEFR, CONEI, CONER, CRSCR, CZI, CZR, DFNU,
FNUP, HZI, HZR, RAZ, RS, RTR1, RZI, RZR, S, SS, STI,
STR, S1I, S1R, S2I, S2R, ZEROI, ZEROR float64
var I, IB, IDUM, IFLAG, IL, K, L, M, NN, NW int
var WR, WI [3]float64
var tmp complex128
CONER = 1.0
NZ = 0
AZ = zabs(complex(ZR, ZI))
if AZ == 0.0E0 {
goto OneSixty
}
// TODO(btracey)
// The original fortran line is "ARM = 1.0D+3*D1MACH(1)". Evidently, in Fortran
// this is interpreted as one to the power of +3*D1MACH(1). While it is possible
// this was intentional, it seems unlikely.
//ARM = 1.0E0 + 3*dmach[1]
//math.Pow(1, 3*dmach[1])
ARM = 1000 * dmach[1]
RTR1 = dsqrt(ARM)
CRSCR = 1.0E0
IFLAG = 0
if AZ < ARM {
goto OneFifty
}
HZR = 0.5E0 * ZR
HZI = 0.5E0 * ZI
CZR = ZEROR
CZI = ZEROI
if AZ <= RTR1 {
goto Ten
}
tmp = zmlt(complex(HZR, HZI), complex(HZR, HZI))
CZR = real(tmp)
CZI = imag(tmp)
Ten:
ACZ = zabs(complex(CZR, CZI))
NN = N
tmp = zlog(complex(HZR, HZI))
CKR = real(tmp)
CKI = imag(tmp)
Twenty:
DFNU = FNU + float64(float32(NN-1))
FNUP = DFNU + 1.0E0
// UNDERFLOW TEST.
AK1R = CKR * DFNU
AK1I = CKI * DFNU
AK = dgamln(FNUP, IDUM)
AK1R = AK1R - AK
if KODE == 2 {
AK1R = AK1R - ZR
}
if AK1R > (-ELIM) {
goto Forty
}
Thirty:
NZ = NZ + 1
YR[NN] = ZEROR
YI[NN] = ZEROI
if ACZ > DFNU {
goto OneNinety
}
NN = NN - 1
if NN == 0 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
goto Twenty
Forty:
if AK1R > (-ALIM) {
goto Fifty
}
IFLAG = 1
SS = 1.0E0 / TOL
CRSCR = TOL
ASCLE = ARM * SS
Fifty:
AA = dexp(AK1R)
if IFLAG == 1 {
AA = AA * SS
}
COEFR = AA * dcos(AK1I)
COEFI = AA * dsin(AK1I)
ATOL = TOL * ACZ / FNUP
IL = min0(2, NN)
for I = 1; I <= IL; I++ {
DFNU = FNU + float64(float32(NN-I))
FNUP = DFNU + 1.0E0
S1R = CONER
S1I = CONEI
if ACZ < TOL*FNUP {
goto Seventy
}
AK1R = CONER
AK1I = CONEI
AK = FNUP + 2.0E0
S = FNUP
AA = 2.0E0
Sixty:
RS = 1.0E0 / S
STR = AK1R*CZR - AK1I*CZI
STI = AK1R*CZI + AK1I*CZR
AK1R = STR * RS
AK1I = STI * RS
S1R = S1R + AK1R
S1I = S1I + AK1I
S = S + AK
AK = AK + 2.0E0
AA = AA * ACZ * RS
if AA > ATOL {
goto Sixty
}
Seventy:
S2R = S1R*COEFR - S1I*COEFI
S2I = S1R*COEFI + S1I*COEFR
WR[I] = S2R
WI[I] = S2I
if IFLAG == 0 {
goto Eighty
}
S2R, S2I, NW, ASCLE, TOL = zuchkOrig(S2R, S2I, NW, ASCLE, TOL)
if NW != 0 {
goto Thirty
}
Eighty:
M = NN - I + 1
YR[M] = S2R * CRSCR
YI[M] = S2I * CRSCR
if I == IL {
continue
}
tmp = zdiv(complex(COEFR, COEFI), complex(HZR, HZI))
STR = real(tmp)
STI = imag(tmp)
COEFR = STR * DFNU
COEFI = STI * DFNU
}
if NN <= 2 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
K = NN - 2
AK = float64(float32(K))
RAZ = 1.0E0 / AZ
STR = ZR * RAZ
STI = -ZI * RAZ
RZR = (STR + STR) * RAZ
RZI = (STI + STI) * RAZ
if IFLAG == 1 {
goto OneTwenty
}
IB = 3
OneHundred:
for I = IB; I <= NN; I++ {
YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2]
YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2]
AK = AK - 1.0E0
K = K - 1
}
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
// RECUR BACKWARD WITH SCALED VALUES.
OneTwenty:
// EXP(-ALIM)=EXP(-ELIM)/TOL=APPROX. ONE PRECISION ABOVE THE
// UNDERFLOW LIMIT = ASCLE = dmach[1)*SS*1.0D+3.
S1R = WR[1]
S1I = WI[1]
S2R = WR[2]
S2I = WI[2]
for L = 3; L <= NN; L++ {
CKR = S2R
CKI = S2I
S2R = S1R + (AK+FNU)*(RZR*CKR-RZI*CKI)
S2I = S1I + (AK+FNU)*(RZR*CKI+RZI*CKR)
S1R = CKR
S1I = CKI
CKR = S2R * CRSCR
CKI = S2I * CRSCR
YR[K] = CKR
YI[K] = CKI
AK = AK - 1.0E0
K = K - 1
if zabs(complex(CKR, CKI)) > ASCLE {
goto OneFourty
}
}
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
OneFourty:
IB = L + 1
if IB > NN {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
goto OneHundred
OneFifty:
NZ = N
if FNU == 0.0E0 {
NZ = NZ - 1
}
OneSixty:
YR[1] = ZEROR
YI[1] = ZEROI
if FNU != 0.0E0 {
goto OneSeventy
}
YR[1] = CONER
YI[1] = CONEI
OneSeventy:
if N == 1 {
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
for I = 2; I <= N; I++ {
YR[I] = ZEROR
YI[I] = ZEROI
}
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
// return WITH NZ<0 if CABS(Z*Z/4)>FNU+N-NZ-1 COMPLETE
// THE CALCULATION IN CBINU WITH N=N-IABS(NZ)
OneNinety:
NZ = -NZ
return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
}
// ZS1S2 TESTS FOR A POSSIBLE UNDERFLOW RESULTING FROM THE
// ADDITION OF THE I AND K FUNCTIONS IN THE ANALYTIC CON-
// TINUATION FORMULA WHERE S1=K FUNCTION AND S2=I FUNCTION.
// ON KODE=1 THE I AND K FUNCTIONS ARE DIFFERENT ORDERS OF
// MAGNITUDE, BUT FOR KODE=2 THEY CAN BE OF THE SAME ORDER
// OF MAGNITUDE AND THE MAXIMUM MUST BE AT LEAST ONE
// PRECISION ABOVE THE UNDERFLOW LIMIT.
func zs1s2Orig(ZRR, ZRI, S1R, S1I, S2R, S2I float64, NZ int, ASCLE, ALIM float64, IUF int) (
ZRRout, ZRIout, S1Rout, S1Iout, S2Rout, S2Iout float64, NZout int, ASCLEout, ALIMout float64, IUFout int) {
var AA, ALN, AS1, AS2, C1I, C1R, S1DI, S1DR, ZEROI, ZEROR float64
var tmp complex128
ZEROR = 0
ZEROI = 0
NZ = 0
AS1 = zabs(complex(S1R, S1I))
AS2 = zabs(complex(S2R, S2I))
if S1R == 0.0E0 && S1I == 0.0E0 {
goto Ten
}
if AS1 == 0.0E0 {
goto Ten
}
ALN = -ZRR - ZRR + dlog(AS1)
S1DR = S1R
S1DI = S1I
S1R = ZEROR
S1I = ZEROI
AS1 = ZEROR
if ALN < (-ALIM) {
goto Ten
}
tmp = zlog(complex(S1DR, S1DI))
C1R = real(tmp)
C1I = imag(tmp)
C1R = C1R - ZRR - ZRR
C1I = C1I - ZRI - ZRI
tmp = zexp(complex(C1R, C1I))
S1R = real(tmp)
S1I = imag(tmp)
AS1 = zabs(complex(S1R, S1I))
IUF = IUF + 1
Ten:
AA = dmax(AS1, AS2)
if AA > ASCLE {
return ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, IUF
}
S1R = ZEROR
S1I = ZEROI
S2R = ZEROR
S2I = ZEROI
NZ = 1
IUF = 0
return ZRR, ZRI, S1R, S1I, S2R, S2I, NZ, ASCLE, ALIM, IUF
}
// ZSHCH COMPUTES THE COMPLEX HYPERBOLIC FUNCTIONS CSH=SINH(X+iY) AND
// CCH=COSH(X+I*Y), WHERE I**2=-1.
// TODO(btracey): use cmplx.Sinh and cmplx.Cosh.
func zshchOrig(ZR, ZI, CSHR, CSHI, CCHR, CCHI float64) (ZRout, ZIout, CSHRout, CSHIout, CCHRout, CCHIout float64) {
var CH, CN, SH, SN float64
SH = math.Sinh(ZR)
CH = math.Cosh(ZR)
SN = dsin(ZI)
CN = dcos(ZI)
CSHR = SH * CN
CSHI = CH * SN
CCHR = CH * CN
CCHI = SH * SN
return ZR, ZI, CSHR, CSHI, CCHR, CCHI
}
func dmax(a, b float64) float64 {
return math.Max(a, b)
}
func dmin(a, b float64) float64 {
return math.Min(a, b)
}
func dabs(a float64) float64 {
return math.Abs(a)
}
func datan(a float64) float64 {
return math.Atan(a)
}
func dtan(a float64) float64 {
return math.Tan(a)
}
func dlog(a float64) float64 {
return math.Log(a)
}
func dsin(a float64) float64 {
return math.Sin(a)
}
func dcos(a float64) float64 {
return math.Cos(a)
}
func dexp(a float64) float64 {
return math.Exp(a)
}
func dsqrt(a float64) float64 {
return math.Sqrt(a)
}
func zmlt(a, b complex128) complex128 {
return a * b
}
func zdiv(a, b complex128) complex128 {
return a / b
}
func zabs(a complex128) float64 {
return cmplx.Abs(a)
}
func zsqrt(a complex128) complex128 {
return cmplx.Sqrt(a)
}
func zexp(a complex128) complex128 {
return cmplx.Exp(a)
}
func zlog(a complex128) complex128 {
return cmplx.Log(a)
}
// Zshch computes the hyperbolic sin and cosine of the input z.
func Zshch(z complex128) (sinh, cosh complex128) {
return cmplx.Sinh(z), cmplx.Cosh(z)
}