123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- // 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 Jn(n int, x float64) float64 {
- const (
- TwoM29 = 1.0 / (1 << 29) // 2**-29 0x3e10000000000000
- Two302 = 1 << 302 // 2**302 0x52D0000000000000
- )
- // special cases
- switch {
- case IsNaN(x):
- return x
- case IsInf(x, 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 n == 0 {
- return J0(x)
- }
- if x == 0 {
- return 0
- }
- if n < 0 {
- n, x = -n, -x
- }
- if n == 1 {
- return J1(x)
- }
- sign := false
- if x < 0 {
- x = -x
- if n&1 == 1 {
- sign = true // odd n and negative x
- }
- }
- var b float64
- if float64(n) <= x {
- // Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x)
- if x >= Two302 { // 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 temp float64
- switch n & 3 {
- case 0:
- temp = Cos(x) + Sin(x)
- case 1:
- temp = -Cos(x) + Sin(x)
- case 2:
- temp = -Cos(x) - Sin(x)
- case 3:
- temp = Cos(x) - Sin(x)
- }
- b = (1 / SqrtPi) * temp / Sqrt(x)
- } else {
- b = J1(x)
- for i, a := 1, J0(x); i < n; i++ {
- a, b = b, b*(float64(i+i)/x)-a // avoid underflow
- }
- }
- } else {
- if x < TwoM29 { // x < 2**-29
- // x is tiny, return the first Taylor expansion of J(n,x)
- // J(n,x) = 1/n!*(x/2)**n - ...
- if n > 33 { // underflow
- b = 0
- } else {
- temp := x * 0.5
- b = temp
- a := 1.0
- for i := 2; i <= n; i++ {
- a *= float64(i) // a = n!
- b *= temp // b = (x/2)**n
- }
- b /= a
- }
- } 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
- w := float64(n+n) / x
- h := 2 / x
- q0 := w
- z := w + h
- q1 := w*z - 1
- k := 1
- for q1 < 1e9 {
- k += 1
- z += h
- q0, q1 = q1, z*q1-q0
- }
- m := n + n
- t := 0.0
- for i := 2 * (n + k); i >= m; i -= 2 {
- t = 1 / (float64(i)/x - t)
- }
- a := t
- b = 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
- tmp := float64(n)
- v := 2 / x
- tmp = tmp * Log(Abs(v*tmp))
- if tmp < 7.09782712893383973096e+02 {
- for i := n - 1; i > 0; i-- {
- di := float64(i + i)
- a, b = b, b*di/x-a
- di -= 2
- }
- } else {
- for i := n - 1; i > 0; i-- {
- di := float64(i + i)
- a, b = b, b*di/x-a
- di -= 2
- // scale b to avoid spurious overflow
- if b > 1e100 {
- a /= b
- t /= b
- b = 1
- }
- }
- }
- b = t * J0(x) / b
- }
- }
- if sign {
- return -b
- }
- return b
- }
- // 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
- // Y1(n, x < 0) = NaN
- // Y1(n, NaN) = NaN
- func Yn(n int, x float64) float64 {
- const Two302 = 1 << 302 // 2**302 0x52D0000000000000
- // special cases
- switch {
- case x < 0 || IsNaN(x):
- return NaN()
- case IsInf(x, 1):
- return 0
- }
- if n == 0 {
- return Y0(x)
- }
- if x == 0 {
- if n < 0 && n&1 == 1 {
- return Inf(1)
- }
- return Inf(-1)
- }
- sign := false
- if n < 0 {
- n = -n
- if n&1 == 1 {
- sign = true // sign true if n < 0 && |n| odd
- }
- }
- if n == 1 {
- if sign {
- return -Y1(x)
- }
- return Y1(x)
- }
- var b float64
- if x >= Two302 { // 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 temp float64
- switch n & 3 {
- case 0:
- temp = Sin(x) - Cos(x)
- case 1:
- temp = -Sin(x) - Cos(x)
- case 2:
- temp = -Sin(x) + Cos(x)
- case 3:
- temp = Sin(x) + Cos(x)
- }
- b = (1 / SqrtPi) * temp / Sqrt(x)
- } else {
- a := Y0(x)
- b = Y1(x)
- // quit if b is -inf
- for i := 1; i < n && !IsInf(b, -1); i++ {
- a, b = b, (float64(i+i)/x)*b-a
- }
- }
- if sign {
- return -b
- }
- return b
- }
|