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