Source File
jn.go
Belonging Package
math
// Copyright 2010 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package math/*Bessel function of the first and second kinds of order n.*/// The original C code and the long comment below are// from FreeBSD's /usr/src/lib/msun/src/e_jn.c and// came with this notice. The go code is a simplified// version of the original C.//// ====================================================// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.//// Developed at SunPro, a Sun Microsystems, Inc. business.// Permission to use, copy, modify, and distribute this// software is freely granted, provided that this notice// is preserved.// ====================================================//// __ieee754_jn(n, x), __ieee754_yn(n, x)// floating point Bessel's function of the 1st and 2nd kind// of order n//// Special cases:// y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;// y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.// Note 2. About jn(n,x), yn(n,x)// For n=0, j0(x) is called,// for n=1, j1(x) is called,// for n<x, forward recursion is used starting// from values of j0(x) and j1(x).// for n>x, a continued fraction approximation to// j(n,x)/j(n-1,x) is evaluated and then backward// recursion is used starting from a supposed value// for j(n,x). The resulting value of j(0,x) is// compared with the actual value to correct the// supposed value of j(n,x).//// yn(n,x) is similar in all respects, except// that forward recursion is used for all// values of n>1.// Jn returns the order-n Bessel function of the first kind.//// Special cases are:// Jn(n, ±Inf) = 0// Jn(n, NaN) = NaNfunc ( int, float64) float64 {const (= 1.0 / (1 << 29) // 2**-29 0x3e10000000000000= 1 << 302 // 2**302 0x52D0000000000000)// special casesswitch {case IsNaN():returncase IsInf(, 0):return 0}// J(-n, x) = (-1)**n * J(n, x), J(n, -x) = (-1)**n * J(n, x)// Thus, J(-n, x) = J(n, -x)if == 0 {return J0()}if == 0 {return 0}if < 0 {, = -, -}if == 1 {return J1()}:= falseif < 0 {= -if &1 == 1 {= true // odd n and negative x}}var float64if float64() <= {// Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x)if >= { // x > 2**302// (x >> n**2)// Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)// Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)// Let s=sin(x), c=cos(x),// xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then//// n sin(xn)*sqt2 cos(xn)*sqt2// ----------------------------------// 0 s-c c+s// 1 -s-c -c+s// 2 -s+c -c-s// 3 s+c c-svar float64switch , := Sincos(); & 3 {case 0:= +case 1:= - +case 2:= - -case 3:= -}= (1 / SqrtPi) * / Sqrt()} else {= J1()for , := 1, J0(); < ; ++ {, = , *(float64(+)/)- // avoid underflow}}} else {if < { // x < 2**-29// x is tiny, return the first Taylor expansion of J(n,x)// J(n,x) = 1/n!*(x/2)**n - ...if > 33 { // underflow= 0} else {:= * 0.5=:= 1.0for := 2; <= ; ++ {*= float64() // a = n!*= // b = (x/2)**n}/=}} else {// use backward recurrence// x x**2 x**2// J(n,x)/J(n-1,x) = ---- ------ ------ .....// 2n - 2(n+1) - 2(n+2)//// 1 1 1// (for large x) = ---- ------ ------ .....// 2n 2(n+1) 2(n+2)// -- - ------ - ------ -// x x x//// Let w = 2n/x and h=2/x, then the above quotient// is equal to the continued fraction:// 1// = -----------------------// 1// w - -----------------// 1// w+h - ---------// w+2h - ...//// To determine how many terms needed, let// Q(0) = w, Q(1) = w(w+h) - 1,// Q(k) = (w+k*h)*Q(k-1) - Q(k-2),// When Q(k) > 1e4 good for single// When Q(k) > 1e9 good for double// When Q(k) > 1e17 good for quadruple// determine k:= float64(+) /:= 2 /:=:= +:= * - 1:= 1for < 1e9 {+++=, = , *-}:= +:= 0.0for := 2 * ( + ); >= ; -= 2 {= 1 / (float64()/ - )}:== 1// estimate log((2/x)**n*n!) = n*log(2/x)+n*ln(n)// Hence, if n*(log(2n/x)) > ...// single 8.8722839355e+01// double 7.09782712893383973096e+02// long double 1.1356523406294143949491931077970765006170e+04// then recurrent value may overflow and the result is// likely underflow to zero:= float64():= 2 /= * Log(Abs(*))if < 7.09782712893383973096e+02 {for := - 1; > 0; -- {:= float64( + ), = , */-}} else {for := - 1; > 0; -- {:= float64( + ), = , */-// scale b to avoid spurious overflowif > 1e100 {/=/== 1}}}= * J0() /}}if {return -}return}// Yn returns the order-n Bessel function of the second kind.//// Special cases are:// Yn(n, +Inf) = 0// Yn(n ≥ 0, 0) = -Inf// Yn(n < 0, 0) = +Inf if n is odd, -Inf if n is even// Yn(n, x < 0) = NaN// Yn(n, NaN) = NaNfunc ( int, float64) float64 {const = 1 << 302 // 2**302 0x52D0000000000000// special casesswitch {case < 0 || IsNaN():return NaN()case IsInf(, 1):return 0}if == 0 {return Y0()}if == 0 {if < 0 && &1 == 1 {return Inf(1)}return Inf(-1)}:= falseif < 0 {= -if &1 == 1 {= true // sign true if n < 0 && |n| odd}}if == 1 {if {return -Y1()}return Y1()}var float64if >= { // x > 2**302// (x >> n**2)// Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)// Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)// Let s=sin(x), c=cos(x),// xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then//// n sin(xn)*sqt2 cos(xn)*sqt2// ----------------------------------// 0 s-c c+s// 1 -s-c -c+s// 2 -s+c -c-s// 3 s+c c-svar float64switch , := Sincos(); & 3 {case 0:= -case 1:= - -case 2:= - +case 3:= +}= (1 / SqrtPi) * / Sqrt()} else {:= Y0()= Y1()// quit if b is -inffor := 1; < && !IsInf(, -1); ++ {, = , (float64(+)/)*-}}if {return -}return}