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