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) = NaN
func ( int, float64) float64 {
const (
= 1.0 / (1 << 29) // 2**-29 0x3e10000000000000
= 1 << 302 // 2**302 0x52D0000000000000
)
// special cases
switch {
case IsNaN():
return
case 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()
}
:= false
if < 0 {
= -
if &1 == 1 {
= true // odd n and negative x
}
}
var float64
if 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-s
var float64
switch , := 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.0
for := 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
:= 1
for < 1e9 {
++
+=
, = , *-
}
:= +
:= 0.0
for := 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 overflow
if > 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) = NaN
func ( int, float64) float64 {
const = 1 << 302 // 2**302 0x52D0000000000000
// special cases
switch {
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)
}
:= false
if < 0 {
= -
if &1 == 1 {
= true // sign true if n < 0 && |n| odd
}
}
if == 1 {
if {
return -Y1()
}
return Y1()
}
var float64
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-s
var float64
switch , := Sincos(); & 3 {
case 0:
= -
case 1:
= - -
case 2:
= - +
case 3:
= +
}
= (1 / SqrtPi) * / Sqrt()
} else {
:= Y0()
= Y1()
// quit if b is -inf
for := 1; < && !IsInf(, -1); ++ {
, = , (float64(+)/)*-
}
}
if {
return -
}
return
}
The pages are generated with Golds v0.6.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |