gonum.org/v1/gonum@v0.15.1-0.20240517103525-f853624cb1bb/mathext/internal/amos/amos.go (about)

     1  // Copyright ©2016 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package amos
     6  
     7  import (
     8  	"math"
     9  	"math/cmplx"
    10  )
    11  
    12  /*
    13  The AMOS functions are included in SLATEC, and the SLATEC guide (http://www.netlib.org/slatec/guide) explicitly states:
    14  "The Library is in the public domain and distributed by the Energy
    15  Science and Technology Software Center."
    16  Mention of AMOS's inclusion in SLATEC goes back at least to this 1985 technical report from Sandia National Labs: http://infoserve.sandia.gov/sand_doc/1985/851018.pdf
    17  */
    18  
    19  // math.NaN() are for padding to keep indexing easy.
    20  var imach = []int{-0, 5, 6, 0, 0, 32, 4, 2, 31, 2147483647, 2, 24, -125, 127, 53, -1021, 1023}
    21  
    22  var dmach = []float64{math.NaN(), 2.23e-308, 1.79e-308, 1.11e-16, 2.22e-16, 0.30103000998497009}
    23  
    24  func abs(a int) int {
    25  	if a >= 0 {
    26  		return a
    27  	}
    28  	return -a
    29  }
    30  
    31  func Zairy(ZR, ZI float64, ID, KODE int) (AIR, AII float64, NZ, IERR int) {
    32  	// zairy is adapted from the original Netlib code by Donald Amos.
    33  	// http://www.netlib.no/netlib/amos/zairy.f
    34  
    35  	// Original comment:
    36  	/*
    37  		C***BEGIN PROLOGUE  ZAIRY
    38  		C***DATE WRITTEN   830501   (YYMMDD)
    39  		C***REVISION DATE  890801   (YYMMDD)
    40  		C***CATEGORY NO.  B5K
    41  		C***KEYWORDS  AIRY FUNCTION,BESSEL FUNCTIONS OF ORDER ONE THIRD
    42  		C***AUTHOR  AMOS, DONALD E., SANDIA NATIONAL LABORATORIES
    43  		C***PURPOSE  TO COMPUTE AIRY FUNCTIONS AI(Z) AND DAI(Z) FOR COMPLEX Z
    44  		C***DESCRIPTION
    45  		C
    46  		C                      ***A DOUBLE PRECISION ROUTINE***
    47  		C         ON KODE=1, ZAIRY COMPUTES THE COMPLEX AIRY FUNCTION AI(Z) OR
    48  		C         ITS DERIVATIVE DAI(Z)/DZ ON ID=0 OR ID=1 RESPECTIVELY. ON
    49  		C         KODE=2, A SCALING OPTION CEXP(ZTA)*AI(Z) OR CEXP(ZTA)*
    50  		C         DAI(Z)/DZ IS PROVIDED TO REMOVE THE EXPONENTIAL DECAY IN
    51  		C         -PI/3<ARG(Z)<PI/3 AND THE EXPONENTIAL GROWTH IN
    52  		C         PI/3<ABS(ARG(Z))<PI WHERE ZTA=(2/3)*Z*CSQRT(Z).
    53  		C
    54  		C         WHILE THE AIRY FUNCTIONS AI(Z) AND DAI(Z)/DZ ARE ANALYTIC IN
    55  		C         THE WHOLE Z PLANE, THE CORRESPONDING SCALED FUNCTIONS DEFINED
    56  		C         FOR KODE=2 HAVE A CUT ALONG THE NEGATIVE REAL AXIS.
    57  		C         DEFINTIONS AND NOTATION ARE FOUND IN THE NBS HANDBOOK OF
    58  		C         MATHEMATICAL FUNCTIONS (REF. 1).
    59  		C
    60  		C         INPUT      ZR,ZI ARE DOUBLE PRECISION
    61  		C           ZR,ZI  - Z=CMPLX(ZR,ZI)
    62  		C           ID     - ORDER OF DERIVATIVE, ID=0 OR ID=1
    63  		C           KODE   - A PARAMETER TO INDICATE THE SCALING OPTION
    64  		C                    KODE= 1  returnS
    65  		C                             AI=AI(Z)                ON ID=0 OR
    66  		C                             AI=DAI(Z)/DZ            ON ID=1
    67  		C                        = 2  returnS
    68  		C                             AI=CEXP(ZTA)*AI(Z)       ON ID=0 OR
    69  		C                             AI=CEXP(ZTA)*DAI(Z)/DZ   ON ID=1 WHERE
    70  		C                             ZTA=(2/3)*Z*CSQRT(Z)
    71  		C
    72  		C         OUTPUT     AIR,AII ARE DOUBLE PRECISION
    73  		C           AIR,AII- COMPLEX ANSWER DEPENDING ON THE CHOICES FOR ID AND
    74  		C                    KODE
    75  		C           NZ     - UNDERFLOW INDICATOR
    76  		C                    NZ= 0   , NORMAL return
    77  		C                    NZ= 1   , AI=CMPLX(0.0E0,0.0E0) DUE TO UNDERFLOW IN
    78  		C                              -PI/3<ARG(Z)<PI/3 ON KODE=1
    79  		C           IERR   - ERROR FLAG
    80  		C                    IERR=0, NORMAL return - COMPUTATION COMPLETED
    81  		C                    IERR=1, INPUT ERROR   - NO COMPUTATION
    82  		C                    IERR=2, OVERFLOW      - NO COMPUTATION, REAL(ZTA)
    83  		C                            TOO LARGE ON KODE=1
    84  		C                    IERR=3, CABS(Z) LARGE      - COMPUTATION COMPLETED
    85  		C                            LOSSES OF SIGNIFCANCE BY ARGUMENT REDUCTION
    86  		C                            PRODUCE LESS THAN HALF OF MACHINE ACCURACY
    87  		C                    IERR=4, CABS(Z) TOO LARGE  - NO COMPUTATION
    88  		C                            COMPLETE LOSS OF ACCURACY BY ARGUMENT
    89  		C                            REDUCTION
    90  		C                    IERR=5, ERROR              - NO COMPUTATION,
    91  		C                            ALGORITHM TERMINATION CONDITION NOT MET
    92  		C
    93  		C***LONG DESCRIPTION
    94  		C
    95  		C         AI AND DAI ARE COMPUTED FOR CABS(Z)>1.0 FROM THE K BESSEL
    96  		C         FUNCTIONS BY
    97  		C
    98  		C            AI(Z)=C*SQRT(Z)*K(1/3,ZTA) , DAI(Z)=-C*Z*K(2/3,ZTA)
    99  		C                           C=1.0/(PI*SQRT(3.0))
   100  		C                            ZTA=(2/3)*Z**(3/2)
   101  		C
   102  		C         WITH THE POWER SERIES FOR CABS(Z)<=1.0.
   103  		C
   104  		C         IN MOST COMPLEX VARIABLE COMPUTATION, ONE MUST EVALUATE ELE-
   105  		C         MENTARY FUNCTIONS. WHEN THE MAGNITUDE OF Z IS LARGE, LOSSES
   106  		C         OF SIGNIFICANCE BY ARGUMENT REDUCTION OCCUR. CONSEQUENTLY, IF
   107  		C         THE MAGNITUDE OF ZETA=(2/3)*Z**1.5 EXCEEDS U1=SQRT(0.5/UR),
   108  		C         THEN LOSSES EXCEEDING HALF PRECISION ARE LIKELY AND AN ERROR
   109  		C         FLAG IERR=3 IS TRIGGERED WHERE UR=math.Max(dmach[4),1.0D-18) IS
   110  		C         DOUBLE PRECISION UNIT ROUNDOFF LIMITED TO 18 DIGITS PRECISION.
   111  		C         ALSO, if THE MAGNITUDE OF ZETA IS LARGER THAN U2=0.5/UR, THEN
   112  		C         ALL SIGNIFICANCE IS LOST AND IERR=4. IN ORDER TO USE THE INT
   113  		C         FUNCTION, ZETA MUST BE FURTHER RESTRICTED NOT TO EXCEED THE
   114  		C         LARGEST INTEGER, U3=I1MACH(9). THUS, THE MAGNITUDE OF ZETA
   115  		C         MUST BE RESTRICTED BY MIN(U2,U3). ON 32 BIT MACHINES, U1,U2,
   116  		C         AND U3 ARE APPROXIMATELY 2.0E+3, 4.2E+6, 2.1E+9 IN SINGLE
   117  		C         PRECISION ARITHMETIC AND 1.3E+8, 1.8E+16, 2.1E+9 IN DOUBLE
   118  		C         PRECISION ARITHMETIC RESPECTIVELY. THIS MAKES U2 AND U3 LIMIT-
   119  		C         ING IN THEIR RESPECTIVE ARITHMETICS. THIS MEANS THAT THE MAG-
   120  		C         NITUDE OF Z CANNOT EXCEED 3.1E+4 IN SINGLE AND 2.1E+6 IN
   121  		C         DOUBLE PRECISION ARITHMETIC. THIS ALSO MEANS THAT ONE CAN
   122  		C         EXPECT TO RETAIN, IN THE WORST CASES ON 32 BIT MACHINES,
   123  		C         NO DIGITS IN SINGLE PRECISION AND ONLY 7 DIGITS IN DOUBLE
   124  		C         PRECISION ARITHMETIC. SIMILAR CONSIDERATIONS HOLD FOR OTHER
   125  		C         MACHINES.
   126  		C
   127  		C         THE APPROXIMATE RELATIVE ERROR IN THE MAGNITUDE OF A COMPLEX
   128  		C         BESSEL FUNCTION CAN BE EXPRESSED BY P*10**S WHERE P=MAX(UNIT
   129  		C         ROUNDOFF,1.0E-18) IS THE NOMINAL PRECISION AND 10**S REPRE-
   130  		C         SENTS THE INCREASE IN ERROR DUE TO ARGUMENT REDUCTION IN THE
   131  		C         ELEMENTARY FUNCTIONS. HERE, S=MAX(1,ABS(LOG10(CABS(Z))),
   132  		C         ABS(LOG10(FNU))) APPROXIMATELY (I.E. S=MAX(1,ABS(EXPONENT OF
   133  		C         CABS(Z),ABS(EXPONENT OF FNU)) ). HOWEVER, THE PHASE ANGLE MAY
   134  		C         HAVE ONLY ABSOLUTE ACCURACY. THIS IS MOST LIKELY TO OCCUR WHEN
   135  		C         ONE COMPONENT (IN ABSOLUTE VALUE) IS LARGER THAN THE OTHER BY
   136  		C         SEVERAL ORDERS OF MAGNITUDE. if ONE COMPONENT IS 10**K LARGER
   137  		C         THAN THE OTHER, THEN ONE CAN EXPECT ONLY MAX(ABS(LOG10(P))-K,
   138  		C         0) SIGNIFICANT DIGITS; OR, STATED ANOTHER WAY, WHEN K EXCEEDS
   139  		C         THE EXPONENT OF P, NO SIGNIFICANT DIGITS REMAIN IN THE SMALLER
   140  		C         COMPONENT. HOWEVER, THE PHASE ANGLE RETAINS ABSOLUTE ACCURACY
   141  		C         BECAUSE, IN COMPLEX ARITHMETIC WITH PRECISION P, THE SMALLER
   142  		C         COMPONENT WILL NOT (AS A RULE) DECREASE BELOW P TIMES THE
   143  		C         MAGNITUDE OF THE LARGER COMPONENT. IN THESE EXTREME CASES,
   144  		C         THE PRINCIPAL PHASE ANGLE IS ON THE ORDER OF +P, -P, PI/2-P,
   145  		C         OR -PI/2+P.
   146  		C
   147  		C***REFERENCES  HANDBOOK OF MATHEMATICAL FUNCTIONS BY M. ABRAMOWITZ
   148  		C                 AND I. A. STEGUN, NBS AMS SERIES 55, U.S. DEPT. OF
   149  		C                 COMMERCE, 1955.
   150  		C
   151  		C               COMPUTATION OF BESSEL FUNCTIONS OF COMPLEX ARGUMENT
   152  		C                 AND LARGE ORDER BY D. E. AMOS, SAND83-0643, MAY, 1983
   153  		C
   154  		C               A SUBROUTINE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX
   155  		C                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, SAND85-
   156  		C                 1018, MAY, 1985
   157  		C
   158  		C               A PORTABLE PACKAGE FOR BESSEL FUNCTIONS OF A COMPLEX
   159  		C                 ARGUMENT AND NONNEGATIVE ORDER BY D. E. AMOS, TRANS.
   160  		C                 MATH. SOFTWARE, 1986
   161  	*/
   162  	var AI, CONE, CSQ, CY, S1, S2, TRM1, TRM2, Z, ZTA, Z3 complex128
   163  	var AA, AD, AK, ALIM, ATRM, AZ, AZ3, BK,
   164  		CC, CK, COEF, CONEI, CONER, CSQI, CSQR, C1, C2, DIG,
   165  		DK, D1, D2, ELIM, FID, FNU, PTR, RL, R1M5, SFAC, STI, STR,
   166  		S1I, S1R, S2I, S2R, TOL, TRM1I, TRM1R, TRM2I, TRM2R, TTH, ZEROI,
   167  		ZEROR, ZTAI, ZTAR, Z3I, Z3R, ALAZ, BB float64
   168  	var IFLAG, K, K1, K2, MR, NN int
   169  	var tmp complex128
   170  
   171  	// Extra element for padding.
   172  	CYR := []float64{math.NaN(), 0}
   173  	CYI := []float64{math.NaN(), 0}
   174  
   175  	_ = AI
   176  	_ = CONE
   177  	_ = CSQ
   178  	_ = CY
   179  	_ = S1
   180  	_ = S2
   181  	_ = TRM1
   182  	_ = TRM2
   183  	_ = Z
   184  	_ = ZTA
   185  	_ = Z3
   186  
   187  	TTH = 6.66666666666666667e-01
   188  	C1 = 3.55028053887817240e-01
   189  	C2 = 2.58819403792806799e-01
   190  	COEF = 1.83776298473930683e-01
   191  	ZEROR = 0
   192  	ZEROI = 0
   193  	CONER = 1
   194  	CONEI = 0
   195  
   196  	NZ = 0
   197  	if ID < 0 || ID > 1 {
   198  		IERR = 1
   199  	}
   200  	if KODE < 1 || KODE > 2 {
   201  		IERR = 1
   202  	}
   203  	if IERR != 0 {
   204  		return
   205  	}
   206  	AZ = cmplx.Abs(complex(ZR, ZI))
   207  	TOL = math.Max(dmach[4], 1.0e-18)
   208  	FID = float64(ID)
   209  	if AZ > 1.0e0 {
   210  		goto Seventy
   211  	}
   212  
   213  	// POWER SERIES FOR CABS(Z)<=1.
   214  	S1R = CONER
   215  	S1I = CONEI
   216  	S2R = CONER
   217  	S2I = CONEI
   218  	if AZ < TOL {
   219  		goto OneSeventy
   220  	}
   221  	AA = AZ * AZ
   222  	if AA < TOL/AZ {
   223  		goto Forty
   224  	}
   225  	TRM1R = CONER
   226  	TRM1I = CONEI
   227  	TRM2R = CONER
   228  	TRM2I = CONEI
   229  	ATRM = 1.0e0
   230  	STR = ZR*ZR - ZI*ZI
   231  	STI = ZR*ZI + ZI*ZR
   232  	Z3R = STR*ZR - STI*ZI
   233  	Z3I = STR*ZI + STI*ZR
   234  	AZ3 = AZ * AA
   235  	AK = 2.0e0 + FID
   236  	BK = 3.0e0 - FID - FID
   237  	CK = 4.0e0 - FID
   238  	DK = 3.0e0 + FID + FID
   239  	D1 = AK * DK
   240  	D2 = BK * CK
   241  	AD = math.Min(D1, D2)
   242  	AK = 24.0e0 + 9.0e0*FID
   243  	BK = 30.0e0 - 9.0e0*FID
   244  	for K = 1; K <= 25; K++ {
   245  		STR = (TRM1R*Z3R - TRM1I*Z3I) / D1
   246  		TRM1I = (TRM1R*Z3I + TRM1I*Z3R) / D1
   247  		TRM1R = STR
   248  		S1R = S1R + TRM1R
   249  		S1I = S1I + TRM1I
   250  		STR = (TRM2R*Z3R - TRM2I*Z3I) / D2
   251  		TRM2I = (TRM2R*Z3I + TRM2I*Z3R) / D2
   252  		TRM2R = STR
   253  		S2R = S2R + TRM2R
   254  		S2I = S2I + TRM2I
   255  		ATRM = ATRM * AZ3 / AD
   256  		D1 = D1 + AK
   257  		D2 = D2 + BK
   258  		AD = math.Min(D1, D2)
   259  		if ATRM < TOL*AD {
   260  			goto Forty
   261  		}
   262  		AK = AK + 18.0e0
   263  		BK = BK + 18.0e0
   264  	}
   265  Forty:
   266  	if ID == 1 {
   267  		goto Fifty
   268  	}
   269  	AIR = S1R*C1 - C2*(ZR*S2R-ZI*S2I)
   270  	AII = S1I*C1 - C2*(ZR*S2I+ZI*S2R)
   271  	if KODE == 1 {
   272  		return
   273  	}
   274  	tmp = cmplx.Sqrt(complex(ZR, ZI))
   275  	STR = real(tmp)
   276  	STI = imag(tmp)
   277  	ZTAR = TTH * (ZR*STR - ZI*STI)
   278  	ZTAI = TTH * (ZR*STI + ZI*STR)
   279  	tmp = cmplx.Exp(complex(ZTAR, ZTAI))
   280  	STR = real(tmp)
   281  	STI = imag(tmp)
   282  	PTR = AIR*STR - AII*STI
   283  	AII = AIR*STI + AII*STR
   284  	AIR = PTR
   285  	return
   286  
   287  Fifty:
   288  	AIR = -S2R * C2
   289  	AII = -S2I * C2
   290  	if AZ <= TOL {
   291  		goto Sixty
   292  	}
   293  	STR = ZR*S1R - ZI*S1I
   294  	STI = ZR*S1I + ZI*S1R
   295  	CC = C1 / (1.0e0 + FID)
   296  	AIR = AIR + CC*(STR*ZR-STI*ZI)
   297  	AII = AII + CC*(STR*ZI+STI*ZR)
   298  
   299  Sixty:
   300  	if KODE == 1 {
   301  		return
   302  	}
   303  	tmp = cmplx.Sqrt(complex(ZR, ZI))
   304  	STR = real(tmp)
   305  	STI = imag(tmp)
   306  	ZTAR = TTH * (ZR*STR - ZI*STI)
   307  	ZTAI = TTH * (ZR*STI + ZI*STR)
   308  	tmp = cmplx.Exp(complex(ZTAR, ZTAI))
   309  	STR = real(tmp)
   310  	STI = imag(tmp)
   311  	PTR = STR*AIR - STI*AII
   312  	AII = STR*AII + STI*AIR
   313  	AIR = PTR
   314  	return
   315  
   316  	// CASE FOR CABS(Z)>1.0.
   317  Seventy:
   318  	FNU = (1.0e0 + FID) / 3.0e0
   319  
   320  	/*
   321  	   SET PARAMETERS RELATED TO MACHINE CONSTANTS.
   322  	   TOL IS THE APPROXIMATE UNIT ROUNDOFF LIMITED TO 1.0D-18.
   323  	   ELIM IS THE APPROXIMATE EXPONENTIAL OVER-&&UNDERFLOW LIMIT.
   324  	   EXP(-ELIM)<EXP(-ALIM)=EXP(-ELIM)/TOL    AND
   325  	   EXP(ELIM)>EXP(ALIM)=EXP(ELIM)*TOL       ARE INTERVALS NEAR
   326  	   UNDERFLOW&&OVERFLOW LIMITS WHERE SCALED ARITHMETIC IS DONE.
   327  	   RL IS THE LOWER BOUNDARY OF THE ASYMPTOTIC EXPANSION FOR LA>=Z.
   328  	   DIG = NUMBER OF BASE 10 DIGITS IN TOL = 10**(-DIG).
   329  	*/
   330  	K1 = imach[15]
   331  	K2 = imach[16]
   332  	R1M5 = dmach[5]
   333  
   334  	K = min(abs(K1), abs(K2))
   335  	ELIM = 2.303e0 * (float64(K)*R1M5 - 3.0e0)
   336  	K1 = imach[14] - 1
   337  	AA = R1M5 * float64(K1)
   338  	DIG = math.Min(AA, 18.0e0)
   339  	AA = AA * 2.303e0
   340  	ALIM = ELIM + math.Max(-AA, -41.45e0)
   341  	RL = 1.2e0*DIG + 3.0e0
   342  	ALAZ = math.Log(AZ)
   343  
   344  	// TEST FOR PROPER RANGE.
   345  	AA = 0.5e0 / TOL
   346  	BB = float64(float32(imach[9])) * 0.5e0
   347  	AA = math.Min(AA, BB)
   348  	AA = math.Pow(AA, TTH)
   349  	if AZ > AA {
   350  		goto TwoSixty
   351  	}
   352  	AA = math.Sqrt(AA)
   353  	if AZ > AA {
   354  		IERR = 3
   355  	}
   356  	tmp = cmplx.Sqrt(complex(ZR, ZI))
   357  	CSQR = real(tmp)
   358  	CSQI = imag(tmp)
   359  	ZTAR = TTH * (ZR*CSQR - ZI*CSQI)
   360  	ZTAI = TTH * (ZR*CSQI + ZI*CSQR)
   361  
   362  	//  RE(ZTA)<=0 WHEN RE(Z)<0, ESPECIALLY WHEN IM(Z) IS SMALL.
   363  	IFLAG = 0
   364  	SFAC = 1.0e0
   365  	AK = ZTAI
   366  	if ZR >= 0.0e0 {
   367  		goto Eighty
   368  	}
   369  	BK = ZTAR
   370  	CK = -math.Abs(BK)
   371  	ZTAR = CK
   372  	ZTAI = AK
   373  
   374  Eighty:
   375  	if ZI != 0.0e0 {
   376  		goto Ninety
   377  	}
   378  	if ZR > 0.0e0 {
   379  		goto Ninety
   380  	}
   381  	ZTAR = 0.0e0
   382  	ZTAI = AK
   383  Ninety:
   384  	AA = ZTAR
   385  	if AA >= 0.0e0 && ZR > 0.0e0 {
   386  		goto OneTen
   387  	}
   388  	if KODE == 2 {
   389  		goto OneHundred
   390  	}
   391  
   392  	// OVERFLOW TEST.
   393  	if AA > (-ALIM) {
   394  		goto OneHundred
   395  	}
   396  	AA = -AA + 0.25e0*ALAZ
   397  	IFLAG = 1
   398  	SFAC = TOL
   399  	if AA > ELIM {
   400  		goto TwoSeventy
   401  	}
   402  
   403  OneHundred:
   404  	// CBKNU AND CACON return EXP(ZTA)*K(FNU,ZTA) ON KODE=2.
   405  	MR = 1
   406  	if ZI < 0.0e0 {
   407  		MR = -1
   408  	}
   409  	_, _, _, _, _, _, CYR, CYI, NN, _, _, _, _ = Zacai(ZTAR, ZTAI, FNU, KODE, MR, 1, CYR, CYI, RL, TOL, ELIM, ALIM)
   410  	if NN < 0 {
   411  		goto TwoEighty
   412  	}
   413  	NZ = NZ + NN
   414  	goto OneThirty
   415  
   416  OneTen:
   417  	if KODE == 2 {
   418  		goto OneTwenty
   419  	}
   420  
   421  	// UNDERFLOW TEST.
   422  	if AA < ALIM {
   423  		goto OneTwenty
   424  	}
   425  	AA = -AA - 0.25e0*ALAZ
   426  	IFLAG = 2
   427  	SFAC = 1.0e0 / TOL
   428  	if AA < (-ELIM) {
   429  		goto TwoTen
   430  	}
   431  OneTwenty:
   432  	_, _, _, _, _, CYR, CYI, NZ, _, _, _ = Zbknu(ZTAR, ZTAI, FNU, KODE, 1, CYR, CYI, TOL, ELIM, ALIM)
   433  
   434  OneThirty:
   435  	S1R = CYR[1] * COEF
   436  	S1I = CYI[1] * COEF
   437  	if IFLAG != 0 {
   438  		goto OneFifty
   439  	}
   440  	if ID == 1 {
   441  		goto OneFourty
   442  	}
   443  	AIR = CSQR*S1R - CSQI*S1I
   444  	AII = CSQR*S1I + CSQI*S1R
   445  	return
   446  OneFourty:
   447  	AIR = -(ZR*S1R - ZI*S1I)
   448  	AII = -(ZR*S1I + ZI*S1R)
   449  	return
   450  OneFifty:
   451  	S1R = S1R * SFAC
   452  	S1I = S1I * SFAC
   453  	if ID == 1 {
   454  		goto OneSixty
   455  	}
   456  	STR = S1R*CSQR - S1I*CSQI
   457  	S1I = S1R*CSQI + S1I*CSQR
   458  	S1R = STR
   459  	AIR = S1R / SFAC
   460  	AII = S1I / SFAC
   461  	return
   462  OneSixty:
   463  	STR = -(S1R*ZR - S1I*ZI)
   464  	S1I = -(S1R*ZI + S1I*ZR)
   465  	S1R = STR
   466  	AIR = S1R / SFAC
   467  	AII = S1I / SFAC
   468  	return
   469  OneSeventy:
   470  	AA = 1.0e+3 * dmach[1]
   471  	S1R = ZEROR
   472  	S1I = ZEROI
   473  	if ID == 1 {
   474  		goto OneNinety
   475  	}
   476  	if AZ <= AA {
   477  		goto OneEighty
   478  	}
   479  	S1R = C2 * ZR
   480  	S1I = C2 * ZI
   481  OneEighty:
   482  	AIR = C1 - S1R
   483  	AII = -S1I
   484  	return
   485  OneNinety:
   486  	AIR = -C2
   487  	AII = 0.0e0
   488  	AA = math.Sqrt(AA)
   489  	if AZ <= AA {
   490  		goto TwoHundred
   491  	}
   492  	S1R = 0.5e0 * (ZR*ZR - ZI*ZI)
   493  	S1I = ZR * ZI
   494  TwoHundred:
   495  	AIR = AIR + C1*S1R
   496  	AII = AII + C1*S1I
   497  	return
   498  TwoTen:
   499  	NZ = 1
   500  	AIR = ZEROR
   501  	AII = ZEROI
   502  	return
   503  TwoSeventy:
   504  	NZ = 0
   505  	IERR = 2
   506  	return
   507  TwoEighty:
   508  	if NN == (-1) {
   509  		goto TwoSeventy
   510  	}
   511  	NZ = 0
   512  	IERR = 5
   513  	return
   514  TwoSixty:
   515  	IERR = 4
   516  	NZ = 0
   517  	return
   518  }
   519  
   520  // sbknu computes the k bessel function in the right half z plane.
   521  func Zbknu(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, TOL, ELIM, ALIM float64) (ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZ int, TOLout, ELIMout, ALIMout float64) {
   522  	/* Old dimension comment.
   523  		DIMENSION YR(N), YI(N), CC(8), CSSR(3), CSRR(3), BRY(3), CYR(2),
   524  	     * CYI(2)
   525  	*/
   526  
   527  	// TODO(btracey): Find which of these are inputs/outputs/both and clean up
   528  	// the function call.
   529  	// YR and YI have length n (but n+1 with better indexing)
   530  	var AA, AK, ASCLE, A1, A2, BB, BK, CAZ,
   531  		CBI, CBR, CCHI, CCHR, CKI, CKR, COEFI, COEFR, CONEI, CONER,
   532  		CRSCR, CSCLR, CSHI, CSHR, CSI, CSR, CTWOR,
   533  		CZEROI, CZEROR, CZI, CZR, DNU, DNU2, DPI, ETEST, FC, FHS,
   534  		FI, FK, FKS, FMUI, FMUR, FPI, FR, G1, G2, HPI, PI, PR, PTI,
   535  		PTR, P1I, P1R, P2I, P2M, P2R, QI, QR, RAK, RCAZ, RTHPI, RZI,
   536  		RZR, R1, S, SMUI, SMUR, SPI, STI, STR, S1I, S1R, S2I, S2R, TM,
   537  		TTH, T1, T2, ELM, CELMR, ZDR, ZDI, AS, ALAS, HELIM float64
   538  
   539  	var I, IFLAG, INU, K, KFLAG, KK, KMAX, KODED, IDUM, J, IC, INUB, NW int
   540  
   541  	var sinh, cosh complex128
   542  	//var sin, cos float64
   543  
   544  	var tmp, p complex128
   545  	var CSSR, CSRR, BRY [4]float64
   546  	var CYR, CYI [3]float64
   547  
   548  	KMAX = 30
   549  	CZEROR = 0
   550  	CZEROI = 0
   551  	CONER = 1
   552  	CONEI = 0
   553  	CTWOR = 2
   554  	R1 = 2
   555  
   556  	DPI = 3.14159265358979324e0
   557  	RTHPI = 1.25331413731550025e0
   558  	SPI = 1.90985931710274403e0
   559  	HPI = 1.57079632679489662e0
   560  	FPI = 1.89769999331517738e0
   561  	TTH = 6.66666666666666666e-01
   562  
   563  	CC := [9]float64{math.NaN(), 5.77215664901532861e-01, -4.20026350340952355e-02,
   564  		-4.21977345555443367e-02, 7.21894324666309954e-03,
   565  		-2.15241674114950973e-04, -2.01348547807882387e-05,
   566  		1.13302723198169588e-06, 6.11609510448141582e-09}
   567  
   568  	CAZ = cmplx.Abs(complex(ZR, ZI))
   569  	CSCLR = 1.0e0 / TOL
   570  	CRSCR = TOL
   571  	CSSR[1] = CSCLR
   572  	CSSR[2] = 1.0e0
   573  	CSSR[3] = CRSCR
   574  	CSRR[1] = CRSCR
   575  	CSRR[2] = 1.0e0
   576  	CSRR[3] = CSCLR
   577  	BRY[1] = 1.0e+3 * dmach[1] / TOL
   578  	BRY[2] = 1.0e0 / BRY[1]
   579  	BRY[3] = dmach[2]
   580  	IFLAG = 0
   581  	KODED = KODE
   582  	RCAZ = 1.0e0 / CAZ
   583  	STR = ZR * RCAZ
   584  	STI = -ZI * RCAZ
   585  	RZR = (STR + STR) * RCAZ
   586  	RZI = (STI + STI) * RCAZ
   587  	INU = int(float32(FNU + 0.5))
   588  	DNU = FNU - float64(INU)
   589  	if math.Abs(DNU) == 0.5e0 {
   590  		goto OneTen
   591  	}
   592  	DNU2 = 0.0e0
   593  	if math.Abs(DNU) > TOL {
   594  		DNU2 = DNU * DNU
   595  	}
   596  	if CAZ > R1 {
   597  		goto OneTen
   598  	}
   599  
   600  	// SERIES FOR CABS(Z)<=R1.
   601  	FC = 1.0e0
   602  	tmp = cmplx.Log(complex(RZR, RZI))
   603  	SMUR = real(tmp)
   604  	SMUI = imag(tmp)
   605  	FMUR = SMUR * DNU
   606  	FMUI = SMUI * DNU
   607  	tmp = complex(FMUR, FMUI)
   608  	sinh = cmplx.Sinh(tmp)
   609  	cosh = cmplx.Cosh(tmp)
   610  	CSHR = real(sinh)
   611  	CSHI = imag(sinh)
   612  	CCHR = real(cosh)
   613  	CCHI = imag(cosh)
   614  	if DNU == 0.0e0 {
   615  		goto Ten
   616  	}
   617  	FC = DNU * DPI
   618  	FC = FC / math.Sin(FC)
   619  	SMUR = CSHR / DNU
   620  	SMUI = CSHI / DNU
   621  Ten:
   622  	A2 = 1.0e0 + DNU
   623  
   624  	// GAM(1-Z)*GAM(1+Z)=PI*Z/SIN(PI*Z), T1=1/GAM(1-DNU), T2=1/GAM(1+DNU).
   625  	T2 = math.Exp(-dgamln(A2, IDUM))
   626  	T1 = 1.0e0 / (T2 * FC)
   627  	if math.Abs(DNU) > 0.1e0 {
   628  		goto Forty
   629  	}
   630  
   631  	// SERIES FOR F0 TO RESOLVE INDETERMINACY FOR SMALL ABS(DNU).
   632  	AK = 1.0e0
   633  	S = CC[1]
   634  	for K = 2; K <= 8; K++ {
   635  		AK = AK * DNU2
   636  		TM = CC[K] * AK
   637  		S = S + TM
   638  		if math.Abs(TM) < TOL {
   639  			goto Thirty
   640  		}
   641  	}
   642  Thirty:
   643  	G1 = -S
   644  	goto Fifty
   645  Forty:
   646  	G1 = (T1 - T2) / (DNU + DNU)
   647  Fifty:
   648  	G2 = (T1 + T2) * 0.5e0
   649  	FR = FC * (CCHR*G1 + SMUR*G2)
   650  	FI = FC * (CCHI*G1 + SMUI*G2)
   651  	tmp = cmplx.Exp(complex(FMUR, FMUI))
   652  	STR = real(tmp)
   653  	STI = imag(tmp)
   654  	PR = 0.5e0 * STR / T2
   655  	PI = 0.5e0 * STI / T2
   656  	tmp = complex(0.5, 0) / complex(STR, STI)
   657  	PTR = real(tmp)
   658  	PTI = imag(tmp)
   659  	QR = PTR / T1
   660  	QI = PTI / T1
   661  	S1R = FR
   662  	S1I = FI
   663  	S2R = PR
   664  	S2I = PI
   665  	AK = 1.0e0
   666  	A1 = 1.0e0
   667  	CKR = CONER
   668  	CKI = CONEI
   669  	BK = 1.0e0 - DNU2
   670  	if INU > 0 || N > 1 {
   671  		goto Eighty
   672  	}
   673  
   674  	// GENERATE K(FNU,Z), 0.0E0 <= FNU < 0.5E0 AND N=1.
   675  	if CAZ < TOL {
   676  		goto Seventy
   677  	}
   678  	tmp = complex(ZR, ZI) * complex(ZR, ZI)
   679  	CZR = real(tmp)
   680  	CZI = imag(tmp)
   681  	CZR = 0.25e0 * CZR
   682  	CZI = 0.25e0 * CZI
   683  	T1 = 0.25e0 * CAZ * CAZ
   684  Sixty:
   685  	FR = (FR*AK + PR + QR) / BK
   686  	FI = (FI*AK + PI + QI) / BK
   687  	STR = 1.0e0 / (AK - DNU)
   688  	PR = PR * STR
   689  	PI = PI * STR
   690  	STR = 1.0e0 / (AK + DNU)
   691  	QR = QR * STR
   692  	QI = QI * STR
   693  	STR = CKR*CZR - CKI*CZI
   694  	RAK = 1.0e0 / AK
   695  	CKI = (CKR*CZI + CKI*CZR) * RAK
   696  	CKR = STR * RAK
   697  	S1R = CKR*FR - CKI*FI + S1R
   698  	S1I = CKR*FI + CKI*FR + S1I
   699  	A1 = A1 * T1 * RAK
   700  	BK = BK + AK + AK + 1.0e0
   701  	AK = AK + 1.0e0
   702  	if A1 > TOL {
   703  		goto Sixty
   704  	}
   705  Seventy:
   706  	YR[1] = S1R
   707  	YI[1] = S1I
   708  	if KODED == 1 {
   709  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
   710  	}
   711  	tmp = cmplx.Exp(complex(ZR, ZI))
   712  	STR = real(tmp)
   713  	STI = imag(tmp)
   714  	tmp = complex(S1R, S1I) * complex(STR, STI)
   715  	YR[1] = real(tmp)
   716  	YI[1] = imag(tmp)
   717  	return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
   718  
   719  	// GENERATE K(DNU,Z) AND K(DNU+1,Z) FOR FORWARD RECURRENCE.
   720  Eighty:
   721  	if CAZ < TOL {
   722  		goto OneHundred
   723  	}
   724  	tmp = complex(ZR, ZI) * complex(ZR, ZI)
   725  	CZR = real(tmp)
   726  	CZI = imag(tmp)
   727  	CZR = 0.25e0 * CZR
   728  	CZI = 0.25e0 * CZI
   729  	T1 = 0.25e0 * CAZ * CAZ
   730  Ninety:
   731  	FR = (FR*AK + PR + QR) / BK
   732  	FI = (FI*AK + PI + QI) / BK
   733  	STR = 1.0e0 / (AK - DNU)
   734  	PR = PR * STR
   735  	PI = PI * STR
   736  	STR = 1.0e0 / (AK + DNU)
   737  	QR = QR * STR
   738  	QI = QI * STR
   739  	STR = CKR*CZR - CKI*CZI
   740  	RAK = 1.0e0 / AK
   741  	CKI = (CKR*CZI + CKI*CZR) * RAK
   742  	CKR = STR * RAK
   743  	S1R = CKR*FR - CKI*FI + S1R
   744  	S1I = CKR*FI + CKI*FR + S1I
   745  	STR = PR - FR*AK
   746  	STI = PI - FI*AK
   747  	S2R = CKR*STR - CKI*STI + S2R
   748  	S2I = CKR*STI + CKI*STR + S2I
   749  	A1 = A1 * T1 * RAK
   750  	BK = BK + AK + AK + 1.0e0
   751  	AK = AK + 1.0e0
   752  	if A1 > TOL {
   753  		goto Ninety
   754  	}
   755  OneHundred:
   756  	KFLAG = 2
   757  	A1 = FNU + 1.0e0
   758  	AK = A1 * math.Abs(SMUR)
   759  	if AK > ALIM {
   760  		KFLAG = 3
   761  	}
   762  	STR = CSSR[KFLAG]
   763  	P2R = S2R * STR
   764  	P2I = S2I * STR
   765  	tmp = complex(P2R, P2I) * complex(RZR, RZI)
   766  	S2R = real(tmp)
   767  	S2I = imag(tmp)
   768  	S1R = S1R * STR
   769  	S1I = S1I * STR
   770  	if KODED == 1 {
   771  		goto TwoTen
   772  	}
   773  	tmp = cmplx.Exp(complex(ZR, ZI))
   774  	FR = real(tmp)
   775  	FI = imag(tmp)
   776  	tmp = complex(S1R, S1I) * complex(FR, FI)
   777  	S1R = real(tmp)
   778  	S1I = imag(tmp)
   779  	tmp = complex(S2R, S2I) * complex(FR, FI)
   780  	S2R = real(tmp)
   781  	S2I = imag(tmp)
   782  	goto TwoTen
   783  
   784  	// IFLAG=0 MEANS NO UNDERFLOW OCCURRED
   785  	// IFLAG=1 MEANS AN UNDERFLOW OCCURRED- COMPUTATION PROCEEDS WITH
   786  	// KODED=2 AND A TEST FOR ON SCALE VALUES IS MADE DURING FORWARD RECURSION
   787  OneTen:
   788  	tmp = cmplx.Sqrt(complex(ZR, ZI))
   789  	STR = real(tmp)
   790  	STI = imag(tmp)
   791  	tmp = complex(RTHPI, CZEROI) / complex(STR, STI)
   792  	COEFR = real(tmp)
   793  	COEFI = imag(tmp)
   794  	KFLAG = 2
   795  	if KODED == 2 {
   796  		goto OneTwenty
   797  	}
   798  	if ZR > ALIM {
   799  		goto TwoNinety
   800  	}
   801  
   802  	STR = math.Exp(-ZR) * CSSR[KFLAG]
   803  	//sin, cos = math.Sincos(ZI)
   804  	STI = -STR * math.Sin(ZI)
   805  	STR = STR * math.Cos(ZI)
   806  	tmp = complex(COEFR, COEFI) * complex(STR, STI)
   807  	COEFR = real(tmp)
   808  	COEFI = imag(tmp)
   809  OneTwenty:
   810  	if math.Abs(DNU) == 0.5e0 {
   811  		goto ThreeHundred
   812  	}
   813  	// MILLER ALGORITHM FOR CABS(Z)>R1.
   814  	AK = math.Cos(DPI * DNU)
   815  	AK = math.Abs(AK)
   816  	if AK == CZEROR {
   817  		goto ThreeHundred
   818  	}
   819  	FHS = math.Abs(0.25e0 - DNU2)
   820  	if FHS == CZEROR {
   821  		goto ThreeHundred
   822  	}
   823  
   824  	// COMPUTE R2=F(E). if CABS(Z)>=R2, USE FORWARD RECURRENCE TO
   825  	// DETERMINE THE BACKWARD INDEX K. R2=F(E) IS A STRAIGHT LINE ON
   826  	// 12<=E<=60. E IS COMPUTED FROM 2**(-E)=B**(1-I1MACH(14))=
   827  	// TOL WHERE B IS THE BASE OF THE ARITHMETIC.
   828  	T1 = float64(imach[14] - 1)
   829  	T1 = T1 * dmach[5] * 3.321928094e0
   830  	T1 = math.Max(T1, 12.0e0)
   831  	T1 = math.Min(T1, 60.0e0)
   832  	T2 = TTH*T1 - 6.0e0
   833  	if ZR != 0.0e0 {
   834  		goto OneThirty
   835  	}
   836  	T1 = HPI
   837  	goto OneFourty
   838  OneThirty:
   839  	T1 = math.Atan(ZI / ZR)
   840  	T1 = math.Abs(T1)
   841  OneFourty:
   842  	if T2 > CAZ {
   843  		goto OneSeventy
   844  	}
   845  	// FORWARD RECURRENCE LOOP WHEN CABS(Z)>=R2.
   846  	ETEST = AK / (DPI * CAZ * TOL)
   847  	FK = CONER
   848  	if ETEST < CONER {
   849  		goto OneEighty
   850  	}
   851  	FKS = CTWOR
   852  	CKR = CAZ + CAZ + CTWOR
   853  	P1R = CZEROR
   854  	P2R = CONER
   855  	for I = 1; I <= KMAX; I++ {
   856  		AK = FHS / FKS
   857  		CBR = CKR / (FK + CONER)
   858  		PTR = P2R
   859  		P2R = CBR*P2R - P1R*AK
   860  		P1R = PTR
   861  		CKR = CKR + CTWOR
   862  		FKS = FKS + FK + FK + CTWOR
   863  		FHS = FHS + FK + FK
   864  		FK = FK + CONER
   865  		STR = math.Abs(P2R) * FK
   866  		if ETEST < STR {
   867  			goto OneSixty
   868  		}
   869  	}
   870  	goto ThreeTen
   871  OneSixty:
   872  	FK = FK + SPI*T1*math.Sqrt(T2/CAZ)
   873  	FHS = math.Abs(0.25 - DNU2)
   874  	goto OneEighty
   875  OneSeventy:
   876  	// COMPUTE BACKWARD INDEX K FOR CABS(Z)<R2.
   877  	A2 = math.Sqrt(CAZ)
   878  	AK = FPI * AK / (TOL * math.Sqrt(A2))
   879  	AA = 3.0e0 * T1 / (1.0e0 + CAZ)
   880  	BB = 14.7e0 * T1 / (28.0e0 + CAZ)
   881  	AK = (math.Log(AK) + CAZ*math.Cos(AA)/(1.0e0+0.008e0*CAZ)) / math.Cos(BB)
   882  	FK = 0.12125e0*AK*AK/CAZ + 1.5e0
   883  OneEighty:
   884  	// BACKWARD RECURRENCE LOOP FOR MILLER ALGORITHM.
   885  	K = int(float32(FK))
   886  	FK = float64(K)
   887  	FKS = FK * FK
   888  	P1R = CZEROR
   889  	P1I = CZEROI
   890  	P2R = TOL
   891  	P2I = CZEROI
   892  	CSR = P2R
   893  	CSI = P2I
   894  	for I = 1; I <= K; I++ {
   895  		A1 = FKS - FK
   896  		AK = (FKS + FK) / (A1 + FHS)
   897  		RAK = 2.0e0 / (FK + CONER)
   898  		CBR = (FK + ZR) * RAK
   899  		CBI = ZI * RAK
   900  		PTR = P2R
   901  		PTI = P2I
   902  		P2R = (PTR*CBR - PTI*CBI - P1R) * AK
   903  		P2I = (PTI*CBR + PTR*CBI - P1I) * AK
   904  		P1R = PTR
   905  		P1I = PTI
   906  		CSR = CSR + P2R
   907  		CSI = CSI + P2I
   908  		FKS = A1 - FK + CONER
   909  		FK = FK - CONER
   910  	}
   911  	// COMPUTE (P2/CS)=(P2/CABS(CS))*(CONJG(CS)/CABS(CS)) FOR BETTER SCALING.
   912  	TM = cmplx.Abs(complex(CSR, CSI))
   913  	PTR = 1.0e0 / TM
   914  	S1R = P2R * PTR
   915  	S1I = P2I * PTR
   916  	CSR = CSR * PTR
   917  	CSI = -CSI * PTR
   918  	tmp = complex(COEFR, COEFI) * complex(S1R, S1I)
   919  	STR = real(tmp)
   920  	STI = imag(tmp)
   921  	tmp = complex(STR, STI) * complex(CSR, CSI)
   922  	S1R = real(tmp)
   923  	S1I = imag(tmp)
   924  	if INU > 0 || N > 1 {
   925  		goto TwoHundred
   926  	}
   927  	ZDR = ZR
   928  	ZDI = ZI
   929  	if IFLAG == 1 {
   930  		goto TwoSeventy
   931  	}
   932  	goto TwoFourty
   933  TwoHundred:
   934  	// COMPUTE P1/P2=(P1/CABS(P2)*CONJG(P2)/CABS(P2) FOR SCALING.
   935  	TM = cmplx.Abs(complex(P2R, P2I))
   936  	PTR = 1.0e0 / TM
   937  	P1R = P1R * PTR
   938  	P1I = P1I * PTR
   939  	P2R = P2R * PTR
   940  	P2I = -P2I * PTR
   941  	tmp = complex(P1R, P1I) * complex(P2R, P2I)
   942  	PTR = real(tmp)
   943  	PTI = imag(tmp)
   944  	STR = DNU + 0.5e0 - PTR
   945  	STI = -PTI
   946  	tmp = complex(STR, STI) / complex(ZR, ZI)
   947  	STR = real(tmp)
   948  	STI = imag(tmp)
   949  	STR = STR + 1.0e0
   950  	tmp = complex(STR, STI) * complex(S1R, S1I)
   951  	S2R = real(tmp)
   952  	S2I = imag(tmp)
   953  
   954  	// FORWARD RECURSION ON THE THREE TERM RECURSION WITH RELATION WITH
   955  	// SCALING NEAR EXPONENT EXTREMES ON KFLAG=1 OR KFLAG=3
   956  TwoTen:
   957  	STR = DNU + 1.0e0
   958  	CKR = STR * RZR
   959  	CKI = STR * RZI
   960  	if N == 1 {
   961  		INU = INU - 1
   962  	}
   963  	if INU > 0 {
   964  		goto TwoTwenty
   965  	}
   966  	if N > 1 {
   967  		goto TwoFifteen
   968  	}
   969  	S1R = S2R
   970  	S1I = S2I
   971  TwoFifteen:
   972  	ZDR = ZR
   973  	ZDI = ZI
   974  	if IFLAG == 1 {
   975  		goto TwoSeventy
   976  	}
   977  	goto TwoFourty
   978  TwoTwenty:
   979  	INUB = 1
   980  	if IFLAG == 1 {
   981  		goto TwoSixtyOne
   982  	}
   983  TwoTwentyFive:
   984  	P1R = CSRR[KFLAG]
   985  	ASCLE = BRY[KFLAG]
   986  	for I = INUB; I <= INU; I++ {
   987  		STR = S2R
   988  		STI = S2I
   989  		S2R = CKR*STR - CKI*STI + S1R
   990  		S2I = CKR*STI + CKI*STR + S1I
   991  		S1R = STR
   992  		S1I = STI
   993  		CKR = CKR + RZR
   994  		CKI = CKI + RZI
   995  		if KFLAG >= 3 {
   996  			continue
   997  		}
   998  		P2R = S2R * P1R
   999  		P2I = S2I * P1R
  1000  		STR = math.Abs(P2R)
  1001  		STI = math.Abs(P2I)
  1002  		P2M = math.Max(STR, STI)
  1003  		if P2M <= ASCLE {
  1004  			continue
  1005  		}
  1006  		KFLAG = KFLAG + 1
  1007  		ASCLE = BRY[KFLAG]
  1008  		S1R = S1R * P1R
  1009  		S1I = S1I * P1R
  1010  		S2R = P2R
  1011  		S2I = P2I
  1012  		STR = CSSR[KFLAG]
  1013  		S1R = S1R * STR
  1014  		S1I = S1I * STR
  1015  		S2R = S2R * STR
  1016  		S2I = S2I * STR
  1017  		P1R = CSRR[KFLAG]
  1018  	}
  1019  	if N != 1 {
  1020  		goto TwoFourty
  1021  	}
  1022  	S1R = S2R
  1023  	S1I = S2I
  1024  TwoFourty:
  1025  	STR = CSRR[KFLAG]
  1026  	YR[1] = S1R * STR
  1027  	YI[1] = S1I * STR
  1028  	if N == 1 {
  1029  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
  1030  	}
  1031  	YR[2] = S2R * STR
  1032  	YI[2] = S2I * STR
  1033  	if N == 2 {
  1034  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
  1035  	}
  1036  	KK = 2
  1037  TwoFifty:
  1038  	KK = KK + 1
  1039  	if KK > N {
  1040  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
  1041  	}
  1042  	P1R = CSRR[KFLAG]
  1043  	ASCLE = BRY[KFLAG]
  1044  	for I = KK; I <= N; I++ {
  1045  		P2R = S2R
  1046  		P2I = S2I
  1047  		S2R = CKR*P2R - CKI*P2I + S1R
  1048  		S2I = CKI*P2R + CKR*P2I + S1I
  1049  		S1R = P2R
  1050  		S1I = P2I
  1051  		CKR = CKR + RZR
  1052  		CKI = CKI + RZI
  1053  		P2R = S2R * P1R
  1054  		P2I = S2I * P1R
  1055  		YR[I] = P2R
  1056  		YI[I] = P2I
  1057  		if KFLAG >= 3 {
  1058  			continue
  1059  		}
  1060  		STR = math.Abs(P2R)
  1061  		STI = math.Abs(P2I)
  1062  		P2M = math.Max(STR, STI)
  1063  		if P2M <= ASCLE {
  1064  			continue
  1065  		}
  1066  		KFLAG = KFLAG + 1
  1067  		ASCLE = BRY[KFLAG]
  1068  		S1R = S1R * P1R
  1069  		S1I = S1I * P1R
  1070  		S2R = P2R
  1071  		S2I = P2I
  1072  		STR = CSSR[KFLAG]
  1073  		S1R = S1R * STR
  1074  		S1I = S1I * STR
  1075  		S2R = S2R * STR
  1076  		S2I = S2I * STR
  1077  		P1R = CSRR[KFLAG]
  1078  	}
  1079  	return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
  1080  
  1081  	// IFLAG=1 CASES, FORWARD RECURRENCE ON SCALED VALUES ON UNDERFLOW.
  1082  TwoSixtyOne:
  1083  	HELIM = 0.5e0 * ELIM
  1084  	ELM = math.Exp(-ELIM)
  1085  	CELMR = ELM
  1086  	ASCLE = BRY[1]
  1087  	ZDR = ZR
  1088  	ZDI = ZI
  1089  	IC = -1
  1090  	J = 2
  1091  	for I = 1; I <= INU; I++ {
  1092  		STR = S2R
  1093  		STI = S2I
  1094  		S2R = STR*CKR - STI*CKI + S1R
  1095  		S2I = STI*CKR + STR*CKI + S1I
  1096  		S1R = STR
  1097  		S1I = STI
  1098  		CKR = CKR + RZR
  1099  		CKI = CKI + RZI
  1100  		AS = cmplx.Abs(complex(S2R, S2I))
  1101  		ALAS = math.Log(AS)
  1102  		P2R = -ZDR + ALAS
  1103  		if P2R < (-ELIM) {
  1104  			goto TwoSixtyThree
  1105  		}
  1106  		tmp = cmplx.Log(complex(S2R, S2I))
  1107  		STR = real(tmp)
  1108  		STI = imag(tmp)
  1109  		P2R = -ZDR + STR
  1110  		P2I = -ZDI + STI
  1111  		P2M = math.Exp(P2R) / TOL
  1112  		// sin, cos = math.Sincos(P2I)
  1113  		P1R = P2M * math.Cos(P2I)
  1114  		P1I = P2M * math.Sin(P2I)
  1115  		p = complex(P1R, P1I)
  1116  		NW = Zuchk(p, ASCLE, TOL)
  1117  		if NW != 0 {
  1118  			goto TwoSixtyThree
  1119  		}
  1120  		J = 3 - J
  1121  		CYR[J] = P1R
  1122  		CYI[J] = P1I
  1123  		if IC == (I - 1) {
  1124  			goto TwoSixtyFour
  1125  		}
  1126  		IC = I
  1127  		continue
  1128  	TwoSixtyThree:
  1129  		if ALAS < HELIM {
  1130  			continue
  1131  		}
  1132  		ZDR = ZDR - ELIM
  1133  		S1R = S1R * CELMR
  1134  		S1I = S1I * CELMR
  1135  		S2R = S2R * CELMR
  1136  		S2I = S2I * CELMR
  1137  	}
  1138  	if N != 1 {
  1139  		goto TwoSeventy
  1140  	}
  1141  	S1R = S2R
  1142  	S1I = S2I
  1143  	goto TwoSeventy
  1144  TwoSixtyFour:
  1145  	KFLAG = 1
  1146  	INUB = I + 1
  1147  	S2R = CYR[J]
  1148  	S2I = CYI[J]
  1149  	J = 3 - J
  1150  	S1R = CYR[J]
  1151  	S1I = CYI[J]
  1152  	if INUB <= INU {
  1153  		goto TwoTwentyFive
  1154  	}
  1155  	if N != 1 {
  1156  		goto TwoFourty
  1157  	}
  1158  	S1R = S2R
  1159  	S1I = S2I
  1160  	goto TwoFourty
  1161  TwoSeventy:
  1162  	YR[1] = S1R
  1163  	YI[1] = S1I
  1164  	if N == 1 {
  1165  		goto TwoEighty
  1166  	}
  1167  	YR[2] = S2R
  1168  	YI[2] = S2I
  1169  TwoEighty:
  1170  	ASCLE = BRY[1]
  1171  	_, _, FNU, N, YR, YI, NZ, RZR, RZI, _, TOL, ELIM = Zkscl(ZDR, ZDI, FNU, N, YR, YI, RZR, RZI, ASCLE, TOL, ELIM)
  1172  	INU = N - NZ
  1173  	if INU <= 0 {
  1174  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
  1175  	}
  1176  	KK = NZ + 1
  1177  	S1R = YR[KK]
  1178  	S1I = YI[KK]
  1179  	YR[KK] = S1R * CSRR[1]
  1180  	YI[KK] = S1I * CSRR[1]
  1181  	if INU == 1 {
  1182  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
  1183  	}
  1184  	KK = NZ + 2
  1185  	S2R = YR[KK]
  1186  	S2I = YI[KK]
  1187  	YR[KK] = S2R * CSRR[1]
  1188  	YI[KK] = S2I * CSRR[1]
  1189  	if INU == 2 {
  1190  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
  1191  	}
  1192  	T2 = FNU + float64(float32(KK-1))
  1193  	CKR = T2 * RZR
  1194  	CKI = T2 * RZI
  1195  	KFLAG = 1
  1196  	goto TwoFifty
  1197  TwoNinety:
  1198  
  1199  	// SCALE BY math.Exp(Z), IFLAG = 1 CASES.
  1200  
  1201  	IFLAG = 1
  1202  	KFLAG = 2
  1203  	goto OneTwenty
  1204  
  1205  	// FNU=HALF ODD INTEGER CASE, DNU=-0.5
  1206  ThreeHundred:
  1207  	S1R = COEFR
  1208  	S1I = COEFI
  1209  	S2R = COEFR
  1210  	S2I = COEFI
  1211  	goto TwoTen
  1212  
  1213  ThreeTen:
  1214  	NZ = -2
  1215  	return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL, ELIM, ALIM
  1216  }
  1217  
  1218  // SET K FUNCTIONS TO ZERO ON UNDERFLOW, CONTINUE RECURRENCE
  1219  // ON SCALED FUNCTIONS UNTIL TWO MEMBERS COME ON SCALE, THEN
  1220  // return WITH MIN(NZ+2,N) VALUES SCALED BY 1/TOL.
  1221  func Zkscl(ZRR, ZRI, FNU float64, N int, YR, YI []float64, RZR, RZI, ASCLE, TOL, ELIM float64) (
  1222  	ZRRout, ZRIout, FNUout float64, Nout int, YRout, YIout []float64, NZ int, RZRout, RZIout, ASCLEout, TOLout, ELIMout float64) {
  1223  	var ACS, AS, CKI, CKR, CSI, CSR, FN, STR, S1I, S1R, S2I,
  1224  		S2R, ZEROI, ZEROR, ZDR, ZDI, CELMR, ELM, HELIM, ALAS float64
  1225  
  1226  	var I, IC, KK, NN, NW int
  1227  	var tmp, c complex128
  1228  	var CYR, CYI [3]float64
  1229  	var sin, cos float64
  1230  
  1231  	// DIMENSION YR(N), YI(N), CYR(2), CYI(2)
  1232  	ZEROR = 0
  1233  	ZEROI = 0
  1234  	IC = 0
  1235  	NN = min(2, N)
  1236  	for I = 1; I <= NN; I++ {
  1237  		S1R = YR[I]
  1238  		S1I = YI[I]
  1239  		CYR[I] = S1R
  1240  		CYI[I] = S1I
  1241  		AS = cmplx.Abs(complex(S1R, S1I))
  1242  		ACS = -ZRR + math.Log(AS)
  1243  		NZ = NZ + 1
  1244  		YR[I] = ZEROR
  1245  		YI[I] = ZEROI
  1246  		if ACS < (-ELIM) {
  1247  			continue
  1248  		}
  1249  
  1250  		tmp = cmplx.Log(complex(S1R, S1I))
  1251  		CSR = real(tmp)
  1252  		CSI = imag(tmp)
  1253  		CSR = CSR - ZRR
  1254  		CSI = CSI - ZRI
  1255  		STR = math.Exp(CSR) / TOL
  1256  		// sin, cos = math.Sincos(CSI)
  1257  		CSR = STR * math.Cos(CSI)
  1258  		CSI = STR * math.Sin(CSI)
  1259  		c = complex(CSR, CSI)
  1260  		NW = Zuchk(c, ASCLE, TOL)
  1261  		if NW != 0 {
  1262  			continue
  1263  		}
  1264  		YR[I] = CSR
  1265  		YI[I] = CSI
  1266  		IC = I
  1267  		NZ = NZ - 1
  1268  	}
  1269  	if N == 1 {
  1270  		return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM
  1271  	}
  1272  	if IC > 1 {
  1273  		goto Twenty
  1274  	}
  1275  	YR[1] = ZEROR
  1276  	YI[1] = ZEROI
  1277  	NZ = 2
  1278  Twenty:
  1279  	if N == 2 {
  1280  		return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM
  1281  	}
  1282  	if NZ == 0 {
  1283  		return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM
  1284  	}
  1285  	FN = FNU + 1.0e0
  1286  	CKR = FN * RZR
  1287  	CKI = FN * RZI
  1288  	S1R = CYR[1]
  1289  	S1I = CYI[1]
  1290  	S2R = CYR[2]
  1291  	S2I = CYI[2]
  1292  	HELIM = 0.5e0 * ELIM
  1293  	ELM = math.Exp(-ELIM)
  1294  	CELMR = ELM
  1295  	ZDR = ZRR
  1296  	ZDI = ZRI
  1297  
  1298  	// FIND TWO CONSECUTIVE Y VALUES ON SCALE. SCALE RECURRENCE IF
  1299  	// S2 GETS LARGER THAN EXP(ELIM/2)
  1300  	for I = 3; I <= N; I++ {
  1301  		KK = I
  1302  		CSR = S2R
  1303  		CSI = S2I
  1304  		S2R = CKR*CSR - CKI*CSI + S1R
  1305  		S2I = CKI*CSR + CKR*CSI + S1I
  1306  		S1R = CSR
  1307  		S1I = CSI
  1308  		CKR = CKR + RZR
  1309  		CKI = CKI + RZI
  1310  		AS = cmplx.Abs(complex(S2R, S2I))
  1311  		ALAS = math.Log(AS)
  1312  		ACS = -ZDR + ALAS
  1313  		NZ = NZ + 1
  1314  		YR[I] = ZEROR
  1315  		YI[I] = ZEROI
  1316  		if ACS < (-ELIM) {
  1317  			goto TwentyFive
  1318  		}
  1319  		tmp = cmplx.Log(complex(S2R, S2I))
  1320  		CSR = real(tmp)
  1321  		CSI = imag(tmp)
  1322  		CSR = CSR - ZDR
  1323  		CSI = CSI - ZDI
  1324  		STR = math.Exp(CSR) / TOL
  1325  		sin, cos = math.Sincos(CSI)
  1326  		CSR = STR * cos
  1327  		CSI = STR * sin
  1328  		c = complex(CSR, CSI)
  1329  		NW = Zuchk(c, ASCLE, TOL)
  1330  		if NW != 0 {
  1331  			goto TwentyFive
  1332  		}
  1333  		YR[I] = CSR
  1334  		YI[I] = CSI
  1335  		NZ = NZ - 1
  1336  		if IC == KK-1 {
  1337  			goto Forty
  1338  		}
  1339  		IC = KK
  1340  		continue
  1341  	TwentyFive:
  1342  		if ALAS < HELIM {
  1343  			continue
  1344  		}
  1345  		ZDR = ZDR - ELIM
  1346  		S1R = S1R * CELMR
  1347  		S1I = S1I * CELMR
  1348  		S2R = S2R * CELMR
  1349  		S2I = S2I * CELMR
  1350  	}
  1351  	NZ = N
  1352  	if IC == N {
  1353  		NZ = N - 1
  1354  	}
  1355  	goto FourtyFive
  1356  Forty:
  1357  	NZ = KK - 2
  1358  FourtyFive:
  1359  	for I = 1; I <= NZ; I++ {
  1360  		YR[I] = ZEROR
  1361  		YI[I] = ZEROI
  1362  	}
  1363  	return ZRR, ZRI, FNU, N, YR, YI, NZ, RZR, RZI, ASCLE, TOL, ELIM
  1364  }
  1365  
  1366  // Zuchk tests whether the magnitude of the real or imaginary part would
  1367  // underflow when y is scaled by tol.
  1368  //
  1369  // y enters as a scaled quantity whose magnitude is greater than
  1370  //
  1371  //	1e3 + 3*dmach(1)/tol
  1372  //
  1373  // y is accepted if the underflow is at least one precision below the magnitude
  1374  // of the largest component. Otherwise an underflow is assumed as the phase angle
  1375  // does not have sufficient accuracy.
  1376  func Zuchk(y complex128, scale, tol float64) int {
  1377  	absR := math.Abs(real(y))
  1378  	absI := math.Abs(imag(y))
  1379  	minAbs := math.Min(absR, absI)
  1380  	if minAbs > scale {
  1381  		return 0
  1382  	}
  1383  	maxAbs := math.Max(absR, absI)
  1384  	minAbs /= tol
  1385  	if maxAbs < minAbs {
  1386  		return 1
  1387  	}
  1388  	return 0
  1389  }
  1390  
  1391  // ZACAI APPLIES THE ANALYTIC CONTINUATION FORMULA
  1392  //
  1393  //	K(FNU,ZN*EXP(MP))=K(FNU,ZN)*EXP(-MP*FNU) - MP*I(FNU,ZN)
  1394  //	      MP=PI*MR*CMPLX(0.0,1.0)
  1395  //
  1396  // TO CONTINUE THE K FUNCTION FROM THE RIGHT HALF TO THE LEFT
  1397  // HALF Z PLANE FOR USE WITH ZAIRY WHERE FNU=1/3 OR 2/3 AND N=1.
  1398  // ZACAI IS THE SAME AS ZACON WITH THE PARTS FOR LARGER ORDERS AND
  1399  // RECURRENCE REMOVED. A RECURSIVE CALL TO ZACON CAN RESULT if ZACON
  1400  // IS CALLED FROM ZAIRY.
  1401  func Zacai(ZR, ZI, FNU float64, KODE, MR, N int, YR, YI []float64, RL, TOL, ELIM, ALIM float64) (
  1402  	ZRout, ZIout, FNUout float64, KODEout, MRout, Nout int, YRout, YIout []float64, NZ int, RLout, TOLout, ELIMout, ALIMout float64) {
  1403  	var ARG, ASCLE, AZ, CSGNR, CSGNI, CSPNR,
  1404  		CSPNI, C1R, C1I, C2R, C2I, DFNU, FMR, PI,
  1405  		SGN, YY, ZNR, ZNI float64
  1406  	var INU, IUF, NN, NW int
  1407  	var zn, c1, c2, z complex128
  1408  	var y []complex128
  1409  	//var sin, cos float64
  1410  
  1411  	CYR := []float64{math.NaN(), 0, 0}
  1412  	CYI := []float64{math.NaN(), 0, 0}
  1413  
  1414  	PI = math.Pi
  1415  	ZNR = -ZR
  1416  	ZNI = -ZI
  1417  	AZ = cmplx.Abs(complex(ZR, ZI))
  1418  	NN = N
  1419  	DFNU = FNU + float64(float32(N-1))
  1420  	if AZ <= 2.0e0 {
  1421  		goto Ten
  1422  	}
  1423  	if AZ*AZ*0.25 > DFNU+1.0e0 {
  1424  		goto Twenty
  1425  	}
  1426  Ten:
  1427  	// POWER SERIES FOR THE I FUNCTION.
  1428  	z = complex(ZNR, ZNI)
  1429  	y = make([]complex128, len(YR))
  1430  	for i, v := range YR {
  1431  		y[i] = complex(v, YI[i])
  1432  	}
  1433  	Zseri(z, FNU, KODE, NN, y[1:], TOL, ELIM, ALIM)
  1434  	for i, v := range y {
  1435  		YR[i] = real(v)
  1436  		YI[i] = imag(v)
  1437  	}
  1438  	goto Forty
  1439  Twenty:
  1440  	if AZ < RL {
  1441  		goto Thirty
  1442  	}
  1443  	// ASYMPTOTIC EXPANSION FOR LARGE Z FOR THE I FUNCTION.
  1444  	ZNR, ZNI, FNU, KODE, _, YR, YI, NW, RL, TOL, ELIM, ALIM = Zasyi(ZNR, ZNI, FNU, KODE, NN, YR, YI, RL, TOL, ELIM, ALIM)
  1445  	if NW < 0 {
  1446  		goto Eighty
  1447  	}
  1448  	goto Forty
  1449  Thirty:
  1450  	// MILLER ALGORITHM NORMALIZED BY THE SERIES FOR THE I FUNCTION
  1451  	ZNR, ZNI, FNU, KODE, _, YR, YI, NW, TOL = Zmlri(ZNR, ZNI, FNU, KODE, NN, YR, YI, TOL)
  1452  	if NW < 0 {
  1453  		goto Eighty
  1454  	}
  1455  Forty:
  1456  	// ANALYTIC CONTINUATION TO THE LEFT HALF PLANE FOR THE K FUNCTION.
  1457  	ZNR, ZNI, FNU, KODE, _, CYR, CYI, NW, TOL, ELIM, ALIM = Zbknu(ZNR, ZNI, FNU, KODE, 1, CYR, CYI, TOL, ELIM, ALIM)
  1458  	if NW != 0 {
  1459  		goto Eighty
  1460  	}
  1461  	FMR = float64(float32(MR))
  1462  	SGN = -math.Copysign(PI, FMR)
  1463  	CSGNR = 0.0e0
  1464  	CSGNI = SGN
  1465  	if KODE == 1 {
  1466  		goto Fifty
  1467  	}
  1468  	YY = -ZNI
  1469  	//sin, cos = math.Sincos(YY)
  1470  	CSGNR = -CSGNI * math.Sin(YY)
  1471  	CSGNI = CSGNI * math.Cos(YY)
  1472  Fifty:
  1473  	// CALCULATE CSPN=EXP(FNU*PI*I) TO MINIMIZE LOSSES OF SIGNIFICANCE
  1474  	// WHEN FNU IS LARGE
  1475  	INU = int(float32(FNU))
  1476  	ARG = (FNU - float64(float32(INU))) * SGN
  1477  	//sin, cos = math.Sincos(ARG)
  1478  	CSPNR = math.Cos(ARG)
  1479  	CSPNI = math.Sin(ARG)
  1480  	if INU%2 == 0 {
  1481  		goto Sixty
  1482  	}
  1483  	CSPNR = -CSPNR
  1484  	CSPNI = -CSPNI
  1485  Sixty:
  1486  	C1R = CYR[1]
  1487  	C1I = CYI[1]
  1488  	C2R = YR[1]
  1489  	C2I = YI[1]
  1490  	if KODE == 1 {
  1491  		goto Seventy
  1492  	}
  1493  	IUF = 0
  1494  	ASCLE = 1.0e+3 * dmach[1] / TOL
  1495  	zn = complex(ZNR, ZNI)
  1496  	c1 = complex(C1R, C1I)
  1497  	c2 = complex(C2R, C2I)
  1498  	c1, c2, NW, _ = Zs1s2(zn, c1, c2, ASCLE, ALIM, IUF)
  1499  	C1R = real(c1)
  1500  	C1I = imag(c1)
  1501  	C2R = real(c2)
  1502  	C2I = imag(c2)
  1503  	NZ = NZ + NW
  1504  Seventy:
  1505  	YR[1] = CSPNR*C1R - CSPNI*C1I + CSGNR*C2R - CSGNI*C2I
  1506  	YI[1] = CSPNR*C1I + CSPNI*C1R + CSGNR*C2I + CSGNI*C2R
  1507  	return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
  1508  Eighty:
  1509  	NZ = -1
  1510  	if NW == -2 {
  1511  		NZ = -2
  1512  	}
  1513  	return ZR, ZI, FNU, KODE, MR, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
  1514  }
  1515  
  1516  // ZASYI COMPUTES THE I BESSEL FUNCTION FOR REAL(Z)>=0.0 BY
  1517  // MEANS OF THE ASYMPTOTIC EXPANSION FOR LARGE CABS(Z) IN THE
  1518  // REGION CABS(Z)>MAX(RL,FNU*FNU/2). NZ=0 IS A NORMAL return.
  1519  // NZ<0 INDICATES AN OVERFLOW ON KODE=1.
  1520  func Zasyi(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, RL, TOL, ELIM, ALIM float64) (
  1521  	ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZ int, RLout, TOLout, ELIMout, ALIMout float64) {
  1522  	var AA, AEZ, AK, AK1I, AK1R, ARG, ARM, ATOL,
  1523  		AZ, BB, BK, CKI, CKR, CONEI, CONER, CS1I, CS1R, CS2I, CS2R, CZI,
  1524  		CZR, DFNU, DKI, DKR, DNU2, EZI, EZR, FDN, PI, P1I,
  1525  		P1R, RAZ, RTPI, RTR1, RZI, RZR, S, SGN, SQK, STI, STR, S2I,
  1526  		S2R, TZI, TZR, ZEROI, ZEROR float64
  1527  
  1528  	var I, IB, IL, INU, J, JL, K, KODED, M, NN int
  1529  	var tmp complex128
  1530  	// var sin, cos float64
  1531  
  1532  	PI = math.Pi
  1533  	RTPI = 0.159154943091895336e0
  1534  	ZEROR = 0
  1535  	ZEROI = 0
  1536  	CONER = 1
  1537  	CONEI = 0
  1538  
  1539  	AZ = cmplx.Abs(complex(ZR, ZI))
  1540  	ARM = 1.0e3 * dmach[1]
  1541  	RTR1 = math.Sqrt(ARM)
  1542  	IL = min(2, N)
  1543  	DFNU = FNU + float64(float32(N-IL))
  1544  
  1545  	// OVERFLOW TEST
  1546  	RAZ = 1.0e0 / AZ
  1547  	STR = ZR * RAZ
  1548  	STI = -ZI * RAZ
  1549  	AK1R = RTPI * STR * RAZ
  1550  	AK1I = RTPI * STI * RAZ
  1551  	tmp = cmplx.Sqrt(complex(AK1R, AK1I))
  1552  	AK1R = real(tmp)
  1553  	AK1I = imag(tmp)
  1554  	CZR = ZR
  1555  	CZI = ZI
  1556  	if KODE != 2 {
  1557  		goto Ten
  1558  	}
  1559  	CZR = ZEROR
  1560  	CZI = ZI
  1561  Ten:
  1562  	if math.Abs(CZR) > ELIM {
  1563  		goto OneHundred
  1564  	}
  1565  	DNU2 = DFNU + DFNU
  1566  	KODED = 1
  1567  	if (math.Abs(CZR) > ALIM) && (N > 2) {
  1568  		goto Twenty
  1569  	}
  1570  	KODED = 0
  1571  	tmp = cmplx.Exp(complex(CZR, CZI))
  1572  	STR = real(tmp)
  1573  	STI = imag(tmp)
  1574  	tmp = complex(AK1R, AK1I) * complex(STR, STI)
  1575  	AK1R = real(tmp)
  1576  	AK1I = imag(tmp)
  1577  Twenty:
  1578  	FDN = 0.0e0
  1579  	if DNU2 > RTR1 {
  1580  		FDN = DNU2 * DNU2
  1581  	}
  1582  	EZR = ZR * 8.0e0
  1583  	EZI = ZI * 8.0e0
  1584  
  1585  	// WHEN Z IS IMAGINARY, THE ERROR TEST MUST BE MADE RELATIVE TO THE
  1586  	// FIRST RECIPROCAL POWER SINCE THIS IS THE LEADING TERM OF THE
  1587  	// EXPANSION FOR THE IMAGINARY PART.
  1588  	AEZ = 8.0e0 * AZ
  1589  	S = TOL / AEZ
  1590  	JL = int(float32(RL+RL)) + 2
  1591  	P1R = ZEROR
  1592  	P1I = ZEROI
  1593  	if ZI == 0.0e0 {
  1594  		goto Thirty
  1595  	}
  1596  
  1597  	// CALCULATE EXP(PI*(0.5+FNU+N-IL)*I) TO MINIMIZE LOSSES OF
  1598  	// SIGNIFICANCE WHEN FNU OR N IS LARGE
  1599  	INU = int(float32(FNU))
  1600  	ARG = (FNU - float64(float32(INU))) * PI
  1601  	INU = INU + N - IL
  1602  	//sin, cos = math.Sincos(ARG)
  1603  	AK = -math.Sin(ARG)
  1604  	BK = math.Cos(ARG)
  1605  	if ZI < 0.0e0 {
  1606  		BK = -BK
  1607  	}
  1608  	P1R = AK
  1609  	P1I = BK
  1610  	if INU%2 == 0 {
  1611  		goto Thirty
  1612  	}
  1613  	P1R = -P1R
  1614  	P1I = -P1I
  1615  Thirty:
  1616  	for K = 1; K <= IL; K++ {
  1617  		SQK = FDN - 1.0e0
  1618  		ATOL = S * math.Abs(SQK)
  1619  		SGN = 1.0e0
  1620  		CS1R = CONER
  1621  		CS1I = CONEI
  1622  		CS2R = CONER
  1623  		CS2I = CONEI
  1624  		CKR = CONER
  1625  		CKI = CONEI
  1626  		AK = 0.0e0
  1627  		AA = 1.0e0
  1628  		BB = AEZ
  1629  		DKR = EZR
  1630  		DKI = EZI
  1631  		// TODO(btracey): This loop is executed tens of thousands of times. Why?
  1632  		// is that really necessary?
  1633  		for J = 1; J <= JL; J++ {
  1634  			tmp = complex(CKR, CKI) / complex(DKR, DKI)
  1635  			STR = real(tmp)
  1636  			STI = imag(tmp)
  1637  			CKR = STR * SQK
  1638  			CKI = STI * SQK
  1639  			CS2R = CS2R + CKR
  1640  			CS2I = CS2I + CKI
  1641  			SGN = -SGN
  1642  			CS1R = CS1R + CKR*SGN
  1643  			CS1I = CS1I + CKI*SGN
  1644  			DKR = DKR + EZR
  1645  			DKI = DKI + EZI
  1646  			AA = AA * math.Abs(SQK) / BB
  1647  			BB = BB + AEZ
  1648  			AK = AK + 8.0e0
  1649  			SQK = SQK - AK
  1650  			if AA <= ATOL {
  1651  				goto Fifty
  1652  			}
  1653  		}
  1654  		goto OneTen
  1655  	Fifty:
  1656  		S2R = CS1R
  1657  		S2I = CS1I
  1658  		if ZR+ZR >= ELIM {
  1659  			goto Sixty
  1660  		}
  1661  		TZR = ZR + ZR
  1662  		TZI = ZI + ZI
  1663  		tmp = cmplx.Exp(complex(-TZR, -TZI))
  1664  		STR = real(tmp)
  1665  		STI = imag(tmp)
  1666  		tmp = complex(STR, STI) * complex(P1R, P1I)
  1667  		STR = real(tmp)
  1668  		STI = imag(tmp)
  1669  		tmp = complex(STR, STI) * complex(CS2R, CS2I)
  1670  		STR = real(tmp)
  1671  		STI = imag(tmp)
  1672  		S2R = S2R + STR
  1673  		S2I = S2I + STI
  1674  	Sixty:
  1675  		FDN = FDN + 8.0e0*DFNU + 4.0e0
  1676  		P1R = -P1R
  1677  		P1I = -P1I
  1678  		M = N - IL + K
  1679  		YR[M] = S2R*AK1R - S2I*AK1I
  1680  		YI[M] = S2R*AK1I + S2I*AK1R
  1681  	}
  1682  	if N <= 2 {
  1683  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
  1684  	}
  1685  	NN = N
  1686  	K = NN - 2
  1687  	AK = float64(float32(K))
  1688  	STR = ZR * RAZ
  1689  	STI = -ZI * RAZ
  1690  	RZR = (STR + STR) * RAZ
  1691  	RZI = (STI + STI) * RAZ
  1692  	IB = 3
  1693  	for I = IB; I <= NN; I++ {
  1694  		YR[K] = (AK+FNU)*(RZR*YR[K+1]-RZI*YI[K+1]) + YR[K+2]
  1695  		YI[K] = (AK+FNU)*(RZR*YI[K+1]+RZI*YR[K+1]) + YI[K+2]
  1696  		AK = AK - 1.0e0
  1697  		K = K - 1
  1698  	}
  1699  	if KODED == 0 {
  1700  		return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
  1701  	}
  1702  	tmp = cmplx.Exp(complex(CZR, CZI))
  1703  	CKR = real(tmp)
  1704  	CKI = imag(tmp)
  1705  	for I = 1; I <= NN; I++ {
  1706  		STR = YR[I]*CKR - YI[I]*CKI
  1707  		YI[I] = YR[I]*CKI + YI[I]*CKR
  1708  		YR[I] = STR
  1709  	}
  1710  	return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
  1711  OneHundred:
  1712  	NZ = -1
  1713  	return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
  1714  OneTen:
  1715  	NZ = -2
  1716  	return ZR, ZI, FNU, KODE, N, YR, YI, NZ, RL, TOL, ELIM, ALIM
  1717  }
  1718  
  1719  // ZMLRI COMPUTES THE I BESSEL FUNCTION FOR RE(Z)>=0.0 BY THE
  1720  // MILLER ALGORITHM NORMALIZED BY A NEUMANN SERIES.
  1721  func Zmlri(ZR, ZI, FNU float64, KODE, N int, YR, YI []float64, TOL float64) (
  1722  	ZRout, ZIout, FNUout float64, KODEout, Nout int, YRout, YIout []float64, NZ int, TOLout float64) {
  1723  	var ACK, AK, AP, AT, AZ, BK, CKI, CKR, CNORMI,
  1724  		CNORMR, CONEI, CONER, FKAP, FKK, FLAM, FNF, PTI, PTR, P1I,
  1725  		P1R, P2I, P2R, RAZ, RHO, RHO2, RZI, RZR, SCLE, STI, STR, SUMI,
  1726  		SUMR, TFNF, TST, ZEROI, ZEROR float64
  1727  	var I, IAZ, IDUM, IFNU, INU, ITIME, K, KK, KM, M int
  1728  	var tmp complex128
  1729  	ZEROR = 0
  1730  	ZEROI = 0
  1731  	CONER = 1
  1732  	CONEI = 0
  1733  
  1734  	SCLE = dmach[1] / TOL
  1735  	AZ = cmplx.Abs(complex(ZR, ZI))
  1736  	IAZ = int(float32(AZ))
  1737  	IFNU = int(float32(FNU))
  1738  	INU = IFNU + N - 1
  1739  	AT = float64(float32(IAZ)) + 1.0e0
  1740  	RAZ = 1.0e0 / AZ
  1741  	STR = ZR * RAZ
  1742  	STI = -ZI * RAZ
  1743  	CKR = STR * AT * RAZ
  1744  	CKI = STI * AT * RAZ
  1745  	RZR = (STR + STR) * RAZ
  1746  	RZI = (STI + STI) * RAZ
  1747  	P1R = ZEROR
  1748  	P1I = ZEROI
  1749  	P2R = CONER
  1750  	P2I = CONEI
  1751  	ACK = (AT + 1.0e0) * RAZ
  1752  	RHO = ACK + math.Sqrt(ACK*ACK-1.0e0)
  1753  	RHO2 = RHO * RHO
  1754  	TST = (RHO2 + RHO2) / ((RHO2 - 1.0e0) * (RHO - 1.0e0))
  1755  	TST = TST / TOL
  1756  
  1757  	// COMPUTE RELATIVE TRUNCATION ERROR INDEX FOR SERIES.
  1758  	//fmt.Println("before loop", P2R, P2I, CKR, CKI, RZR, RZI, TST, AK)
  1759  	AK = AT
  1760  	for I = 1; I <= 80; I++ {
  1761  		PTR = P2R
  1762  		PTI = P2I
  1763  		P2R = P1R - (CKR*PTR - CKI*PTI)
  1764  		P2I = P1I - (CKI*PTR + CKR*PTI)
  1765  		P1R = PTR
  1766  		P1I = PTI
  1767  		CKR = CKR + RZR
  1768  		CKI = CKI + RZI
  1769  		AP = cmplx.Abs(complex(P2R, P2I))
  1770  		if AP > TST*AK*AK {
  1771  			goto Twenty
  1772  		}
  1773  		AK = AK + 1.0e0
  1774  	}
  1775  	goto OneTen
  1776  Twenty:
  1777  	I = I + 1
  1778  	K = 0
  1779  	if INU < IAZ {
  1780  		goto Forty
  1781  	}
  1782  	// COMPUTE RELATIVE TRUNCATION ERROR FOR RATIOS.
  1783  	P1R = ZEROR
  1784  	P1I = ZEROI
  1785  	P2R = CONER
  1786  	P2I = CONEI
  1787  	AT = float64(float32(INU)) + 1.0e0
  1788  	STR = ZR * RAZ
  1789  	STI = -ZI * RAZ
  1790  	CKR = STR * AT * RAZ
  1791  	CKI = STI * AT * RAZ
  1792  	ACK = AT * RAZ
  1793  	TST = math.Sqrt(ACK / TOL)
  1794  	ITIME = 1
  1795  	for K = 1; K <= 80; K++ {
  1796  		PTR = P2R
  1797  		PTI = P2I
  1798  		P2R = P1R - (CKR*PTR - CKI*PTI)
  1799  		P2I = P1I - (CKR*PTI + CKI*PTR)
  1800  		P1R = PTR
  1801  		P1I = PTI
  1802  		CKR = CKR + RZR
  1803  		CKI = CKI + RZI
  1804  		AP = cmplx.Abs(complex(P2R, P2I))
  1805  		if AP < TST {
  1806  			continue
  1807  		}
  1808  		if ITIME == 2 {
  1809  			goto Forty
  1810  		}
  1811  		ACK = cmplx.Abs(complex(CKR, CKI))
  1812  		FLAM = ACK + math.Sqrt(ACK*ACK-1.0e0)
  1813  		FKAP = AP / cmplx.Abs(complex(P1R, P1I))
  1814  		RHO = math.Min(FLAM, FKAP)
  1815  		TST = TST * math.Sqrt(RHO/(RHO*RHO-1.0e0))
  1816  		ITIME = 2
  1817  	}
  1818  	goto OneTen
  1819  Forty:
  1820  	// BACKWARD RECURRENCE AND SUM NORMALIZING RELATION.
  1821  	K = K + 1
  1822  	KK = max(I+IAZ, K+INU)
  1823  	FKK = float64(float32(KK))
  1824  	P1R = ZEROR
  1825  	P1I = ZEROI
  1826  
  1827  	// SCALE P2 AND SUM BY SCLE.
  1828  	P2R = SCLE
  1829  	P2I = ZEROI
  1830  	FNF = FNU - float64(float32(IFNU))
  1831  	TFNF = FNF + FNF
  1832  	BK = dgamln(FKK+TFNF+1.0e0, IDUM) - dgamln(FKK+1.0e0, IDUM) - dgamln(TFNF+1.0e0, IDUM)
  1833  	BK = math.Exp(BK)
  1834  	SUMR = ZEROR
  1835  	SUMI = ZEROI
  1836  	KM = KK - INU
  1837  	for I = 1; I <= KM; I++ {
  1838  		PTR = P2R
  1839  		PTI = P2I
  1840  		P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)
  1841  		P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI)
  1842  		P1R = PTR
  1843  		P1I = PTI
  1844  		AK = 1.0e0 - TFNF/(FKK+TFNF)
  1845  		ACK = BK * AK
  1846  		SUMR = SUMR + (ACK+BK)*P1R
  1847  		SUMI = SUMI + (ACK+BK)*P1I
  1848  		BK = ACK
  1849  		FKK = FKK - 1.0e0
  1850  	}
  1851  	YR[N] = P2R
  1852  	YI[N] = P2I
  1853  	if N == 1 {
  1854  		goto Seventy
  1855  	}
  1856  	for I = 2; I <= N; I++ {
  1857  		PTR = P2R
  1858  		PTI = P2I
  1859  		P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)
  1860  		P2I = P1I + (FKK+FNF)*(RZI*PTR+RZR*PTI)
  1861  		P1R = PTR
  1862  		P1I = PTI
  1863  		AK = 1.0e0 - TFNF/(FKK+TFNF)
  1864  		ACK = BK * AK
  1865  		SUMR = SUMR + (ACK+BK)*P1R
  1866  		SUMI = SUMI + (ACK+BK)*P1I
  1867  		BK = ACK
  1868  		FKK = FKK - 1.0e0
  1869  		M = N - I + 1
  1870  		YR[M] = P2R
  1871  		YI[M] = P2I
  1872  	}
  1873  Seventy:
  1874  	if IFNU <= 0 {
  1875  		goto Ninety
  1876  	}
  1877  	for I = 1; I <= IFNU; I++ {
  1878  		PTR = P2R
  1879  		PTI = P2I
  1880  		P2R = P1R + (FKK+FNF)*(RZR*PTR-RZI*PTI)
  1881  		P2I = P1I + (FKK+FNF)*(RZR*PTI+RZI*PTR)
  1882  		P1R = PTR
  1883  		P1I = PTI
  1884  		AK = 1.0e0 - TFNF/(FKK+TFNF)
  1885  		ACK = BK * AK
  1886  		SUMR = SUMR + (ACK+BK)*P1R
  1887  		SUMI = SUMI + (ACK+BK)*P1I
  1888  		BK = ACK
  1889  		FKK = FKK - 1.0e0
  1890  	}
  1891  Ninety:
  1892  	PTR = ZR
  1893  	PTI = ZI
  1894  	if KODE == 2 {
  1895  		PTR = ZEROR
  1896  	}
  1897  	tmp = cmplx.Log(complex(RZR, RZI))
  1898  	STR = real(tmp)
  1899  	STI = imag(tmp)
  1900  	P1R = -FNF*STR + PTR
  1901  	P1I = -FNF*STI + PTI
  1902  	AP = dgamln(1.0e0+FNF, IDUM)
  1903  	PTR = P1R - AP
  1904  	PTI = P1I
  1905  
  1906  	// THE DIVISION CEXP(PT)/(SUM+P2) IS ALTERED TO AVOID OVERFLOW
  1907  	// IN THE DENOMINATOR BY SQUARING LARGE QUANTITIES.
  1908  	P2R = P2R + SUMR
  1909  	P2I = P2I + SUMI
  1910  	AP = cmplx.Abs(complex(P2R, P2I))
  1911  	P1R = 1.0e0 / AP
  1912  	tmp = cmplx.Exp(complex(PTR, PTI))
  1913  	STR = real(tmp)
  1914  	STI = imag(tmp)
  1915  	CKR = STR * P1R
  1916  	CKI = STI * P1R
  1917  	PTR = P2R * P1R
  1918  	PTI = -P2I * P1R
  1919  	tmp = complex(CKR, CKI) * complex(PTR, PTI)
  1920  	CNORMR = real(tmp)
  1921  	CNORMI = imag(tmp)
  1922  	for I = 1; I <= N; I++ {
  1923  		STR = YR[I]*CNORMR - YI[I]*CNORMI
  1924  		YI[I] = YR[I]*CNORMI + YI[I]*CNORMR
  1925  		YR[I] = STR
  1926  	}
  1927  	return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL
  1928  OneTen:
  1929  	NZ = -2
  1930  	return ZR, ZI, FNU, KODE, N, YR, YI, NZ, TOL
  1931  }
  1932  
  1933  // Zseri computes the I bessel function for real(z) >= 0 by means of the power
  1934  // series for large |z| in the region |z| <= 2*sqrt(fnu+1).
  1935  //
  1936  // nz = 0 is a normal return. nz > 0 means that the last nz components were set
  1937  // to zero due to underflow. nz < 0 means that underflow occurred, but the
  1938  // condition |z| <= 2*sqrt(fnu+1) was violated and the computation must be
  1939  // completed in another routine with n -= abs(nz).
  1940  func Zseri(z complex128, fnu float64, kode, n int, y []complex128, tol, elim, alim float64) (nz int) {
  1941  	// TODO(btracey): The original fortran line is "ARM = 1.0D+3*D1MACH(1)". Evidently, in Fortran
  1942  	// this is interpreted as one to the power of +3*D1MACH(1). While it is possible
  1943  	// this was intentional, it seems unlikely.
  1944  	arm := 1000 * dmach[1]
  1945  	az := cmplx.Abs(z)
  1946  	if az < arm {
  1947  		for i := 0; i < n; i++ {
  1948  			y[i] = 0
  1949  		}
  1950  		if fnu == 0 {
  1951  			y[0] = 1
  1952  			n--
  1953  		}
  1954  		if az == 0 {
  1955  			return 0
  1956  		}
  1957  		return n
  1958  	}
  1959  	hz := 0.5 * z
  1960  	var cz complex128
  1961  	var acz float64
  1962  	if az > math.Sqrt(arm) {
  1963  		cz = hz * hz
  1964  		acz = cmplx.Abs(cz)
  1965  	}
  1966  	NN := n
  1967  	ck := cmplx.Log(hz)
  1968  	var ak1 complex128
  1969  	for {
  1970  		dfnu := fnu + float64(NN-1)
  1971  		// Underflow test.
  1972  		ak1 = ck * complex(dfnu, 0)
  1973  		ak := dgamln(dfnu+1, 0)
  1974  		ak1 -= complex(ak, 0)
  1975  		if kode == 2 {
  1976  			ak1 -= complex(real(z), 0)
  1977  		}
  1978  		if real(ak1) > -elim {
  1979  			break
  1980  		}
  1981  		nz++
  1982  		y[NN-1] = 0
  1983  		if acz > dfnu {
  1984  			// Return with nz < 0 if abs(Z*Z/4)>fnu+u-nz-1 complete the calculation
  1985  			// in cbinu with n = n - abs(nz).
  1986  			nz *= -1
  1987  			return nz
  1988  		}
  1989  		NN--
  1990  		if NN == 0 {
  1991  			return nz
  1992  		}
  1993  	}
  1994  	crscr := 1.0
  1995  	var flag int
  1996  	var scale float64
  1997  	aa := real(ak1)
  1998  	if aa <= -alim {
  1999  		flag = 1
  2000  		crscr = tol
  2001  		scale = arm / tol
  2002  		aa -= math.Log(tol)
  2003  	}
  2004  	var w [2]complex128
  2005  	for {
  2006  		coef := cmplx.Exp(complex(aa, imag(ak1)))
  2007  		atol := tol * acz / (fnu + float64(NN))
  2008  		for i := 0; i < min(2, NN); i++ {
  2009  			FNUP := fnu + float64(NN-i)
  2010  			s1 := 1 + 0i
  2011  			if acz >= tol*FNUP {
  2012  				ak2 := 1 + 0i
  2013  				ak := FNUP + 2
  2014  				S := FNUP
  2015  				scl := 2.0
  2016  				first := true
  2017  				for first || scl > atol {
  2018  					ak2 = ak2 * cz * complex(1/S, 0)
  2019  					scl *= acz / S
  2020  					s1 += ak2
  2021  					S += ak
  2022  					ak += 2
  2023  					first = false
  2024  				}
  2025  			}
  2026  			s2 := s1 * coef
  2027  			w[i] = s2
  2028  			if flag == 1 {
  2029  				if Zuchk(s2, scale, tol) != 0 {
  2030  					var full bool
  2031  					var dfnu float64
  2032  					// This code is similar to the code that exists above. The
  2033  					// code copying is here because the original Fortran used
  2034  					// a goto to solve the loop-and-a-half problem. Removing the
  2035  					// goto makes the behavior of the function and variable scoping
  2036  					// much clearer, but requires copying this code due to Go's
  2037  					// goto rules.
  2038  					for {
  2039  						if full {
  2040  							dfnu = fnu + float64(NN-1)
  2041  							// Underflow test.
  2042  							ak1 = ck * complex(dfnu, 0)
  2043  							ak1 -= complex(dgamln(dfnu+1, 0), 0)
  2044  							if kode == 2 {
  2045  								ak1 -= complex(real(z), 0)
  2046  							}
  2047  							if real(ak1) > -elim {
  2048  								break
  2049  							}
  2050  						} else {
  2051  							full = true
  2052  						}
  2053  						nz++
  2054  						y[NN-1] = 0
  2055  						if acz > dfnu {
  2056  							// Return with nz < 0 if abs(Z*Z/4)>fnu+u-nz-1 complete the calculation
  2057  							// in cbinu with n = n - abs(nz).
  2058  							nz *= -1
  2059  							return nz
  2060  						}
  2061  						NN--
  2062  						if NN == 0 {
  2063  							return nz
  2064  						}
  2065  					}
  2066  					continue
  2067  				}
  2068  			}
  2069  			y[NN-i-1] = s2 * complex(crscr, 0)
  2070  			coef /= hz
  2071  			coef *= complex(FNUP-1, 0)
  2072  		}
  2073  		break
  2074  	}
  2075  	if NN <= 2 {
  2076  		return nz
  2077  	}
  2078  	rz := complex(2*real(z)/(az*az), -2*imag(z)/(az*az))
  2079  	if flag == 0 {
  2080  		for i := NN - 3; i >= 0; i-- {
  2081  			y[i] = complex(float64(i+1)+fnu, 0)*rz*y[i+1] + y[i+2]
  2082  		}
  2083  		return nz
  2084  	}
  2085  
  2086  	// exp(-alim)=exp(-elim)/tol=approximately one digit of precision above the
  2087  	// underflow limit, which equals scale = dmach[1)*SS*1e3.
  2088  	s1 := w[0]
  2089  	s2 := w[1]
  2090  	for K := NN - 3; K >= 0; K-- {
  2091  		s1, s2 = s2, s1+complex(float64(K+1)+fnu, 0)*(rz*s2)
  2092  		ck := s2 * complex(crscr, 0)
  2093  		y[K] = ck
  2094  		if cmplx.Abs(ck) > scale {
  2095  			for ; K >= 0; K-- {
  2096  				y[K] = complex(float64(K+1)+fnu, 0)*rz*y[K+1] + y[K+2]
  2097  			}
  2098  			return nz
  2099  		}
  2100  	}
  2101  	return nz
  2102  }
  2103  
  2104  // Zs1s2 tests for a possible underflow resulting from the addition of the I and
  2105  // K functions in the analytic continuation formula where s1 == K function and
  2106  // s2 == I function.
  2107  //
  2108  // When kode == 1, the I and K functions are different orders of magnitude.
  2109  //
  2110  // When kode == 2, they may both be of the same order of magnitude, but the maximum
  2111  // must be at least one precision above the underflow limit.
  2112  func Zs1s2(zr, s1, s2 complex128, scale, lim float64, iuf int) (s1o, s2o complex128, nz, iufo int) {
  2113  	if s1 == 0 || math.Log(cmplx.Abs(s1))-2*real(zr) < -lim {
  2114  		if cmplx.Abs(s2) > scale {
  2115  			return 0, s2, 0, iuf
  2116  		}
  2117  		return 0, 0, 1, 0
  2118  	}
  2119  	// TODO(btracey): Written like this for numerical rounding reasons.
  2120  	// Fix once we're sure other changes are correct.
  2121  	s1 = cmplx.Exp(cmplx.Log(s1) - zr - zr)
  2122  	if math.Max(cmplx.Abs(s1), cmplx.Abs(s2)) > scale {
  2123  		return s1, s2, 0, iuf + 1
  2124  	}
  2125  	return 0, 0, 1, 0
  2126  }
  2127  
  2128  func dgamln(z float64, ierr int) float64 {
  2129  	//return amoslib.DgamlnFort(z)
  2130  	// Go implementation.
  2131  	if z < 0 {
  2132  		return 0
  2133  	}
  2134  	a2, _ := math.Lgamma(z)
  2135  	return a2
  2136  }