mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 21:40:52 -05:00 
			
		
		
		
	
		
			
	
	
		
			195 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			195 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[section:mbessel Modified Bessel Functions of the First and Second Kinds]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Synopsis]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`#include <boost/math/special_functions/bessel.hpp>`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class T1, class T2>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` cyl_bessel_i(T1 v, T2 x);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class T1, class T2, class ``__Policy``>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` cyl_bessel_i(T1 v, T2 x, const ``__Policy``&);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class T1, class T2>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` cyl_bessel_k(T1 v, T2 x);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   template <class T1, class T2, class ``__Policy``>
							 | 
						||
| 
								 | 
							
								   ``__sf_result`` cyl_bessel_k(T1 v, T2 x, const ``__Policy``&);
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								[h4 Description]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The functions __cyl_bessel_i and __cyl_bessel_k return the result of the
							 | 
						||
| 
								 | 
							
								modified Bessel functions of the first and second kind respectively:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cyl_bessel_i(v, x) = I[sub v](x)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cyl_bessel_k(v, x) = K[sub v](x)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								where:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel2]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel3]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The return type of these functions is computed using the __arg_promotion_rules
							 | 
						||
| 
								 | 
							
								when T1 and T2 are different types.  The functions are also optimised for the
							 | 
						||
| 
								 | 
							
								relatively common case that T1 is an integer.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[optional_policy]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The functions return the result of __domain_error whenever the result is
							 | 
						||
| 
								 | 
							
								undefined or complex.  For __cyl_bessel_j this occurs when `x < 0` and v is not
							 | 
						||
| 
								 | 
							
								an integer, or when `x == 0` and `v != 0`.  For __cyl_neumann this occurs
							 | 
						||
| 
								 | 
							
								when `x <= 0`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The following graph illustrates the exponential behaviour of I[sub v].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[graph cyl_bessel_i]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The following graph illustrates the exponential decay of K[sub v].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[graph cyl_bessel_k]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Testing]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								There are two sets of test values: spot values calculated using
							 | 
						||
| 
								 | 
							
								[@http://functions.wolfram.com functions.wolfram.com],
							 | 
						||
| 
								 | 
							
								and a much larger set of tests computed using
							 | 
						||
| 
								 | 
							
								a simplified version of this implementation
							 | 
						||
| 
								 | 
							
								(with all the special case handling removed).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Accuracy]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The following tables show how the accuracy of these functions
							 | 
						||
| 
								 | 
							
								varies on various platforms, along with comparison to other libraries.  
							 | 
						||
| 
								 | 
							
								Note that only results for the widest floating-point type on the 
							 | 
						||
| 
								 | 
							
								system are given, as narrower types have __zero_error.  All values
							 | 
						||
| 
								 | 
							
								are relative errors in units of epsilon.  Note that our test suite
							 | 
						||
| 
								 | 
							
								includes some fairly extreme inputs which results in most of the worst
							 | 
						||
| 
								 | 
							
								problem cases in other libraries:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[table_cyl_bessel_i_integer_orders_]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[table_cyl_bessel_i]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[table_cyl_bessel_k_integer_orders_]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[table_cyl_bessel_k]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[h4 Implementation]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The following are handled as special cases first:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When computing I[sub v][space] for ['x < 0], then [nu][space] must be an integer
							 | 
						||
| 
								 | 
							
								or a domain error occurs.  If [nu][space] is an integer, then the function is
							 | 
						||
| 
								 | 
							
								odd if [nu][space] is odd and even if [nu][space] is even, and we can reflect to
							 | 
						||
| 
								 | 
							
								['x > 0].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For I[sub v][space] with v equal to 0, 1 or 0.5 are handled as special cases.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The 0 and 1 cases use minimax rational approximations on
							 | 
						||
| 
								 | 
							
								finite and infinite intervals. The coefficients are from:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* J.M. Blair and C.A. Edwards, ['Stable rational minimax approximations
							 | 
						||
| 
								 | 
							
								    to the modified Bessel functions I_0(x) and I_1(x)], Atomic Energy of Canada
							 | 
						||
| 
								 | 
							
								    Limited Report 4928, Chalk River, 1974.
							 | 
						||
| 
								 | 
							
								* S. Moshier, ['Methods and Programs for Mathematical Functions],
							 | 
						||
| 
								 | 
							
								    Ellis Horwood Ltd, Chichester, 1989.    
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								While the 0.5 case is a simple trigonometric function:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								I[sub 0.5](x) = sqrt(2 / [pi]x) * sinh(x)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For K[sub v][space] with /v/ an integer, the result is calculated using the
							 | 
						||
| 
								 | 
							
								recurrence relation:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel5]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								starting from K[sub 0][space] and K[sub 1][space] which are calculated
							 | 
						||
| 
								 | 
							
								using rational the approximations above.  These rational approximations are
							 | 
						||
| 
								 | 
							
								accurate to around 19 digits, and are therefore only used when T has 
							 | 
						||
| 
								 | 
							
								no more than 64 binary digits of precision.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When /x/ is small compared to /v/, I[sub v]x[space] is best computed directly from the series:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel17]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In the general case, we first normalize [nu][space] to \[[^0, [inf]])
							 | 
						||
| 
								 | 
							
								with the help of the reflection formulae:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel9]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel10]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Let [mu][space] = [nu] - floor([nu] + 1/2), then [mu][space] is the fractional part of 
							 | 
						||
| 
								 | 
							
								[nu][space] such that |[mu]| <= 1/2 (we need this for convergence later). The idea is to
							 | 
						||
| 
								 | 
							
								calculate K[sub [mu]](x) and K[sub [mu]+1](x), and use them to obtain
							 | 
						||
| 
								 | 
							
								I[sub [nu]](x) and K[sub [nu]](x).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The algorithm is proposed by Temme in 
							 | 
						||
| 
								 | 
							
								N.M. Temme, ['On the numerical evaluation of the modified bessel function
							 | 
						||
| 
								 | 
							
								    of the third kind], Journal of Computational Physics, vol 19, 324 (1975), 
							 | 
						||
| 
								 | 
							
								which needs two continued fractions as well as the Wronskian:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel11]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel12]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel8]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The continued fractions are computed using the modified Lentz's method
							 | 
						||
| 
								 | 
							
								(W.J. Lentz, ['Generating Bessel functions in Mie scattering calculations
							 | 
						||
| 
								 | 
							
								    using continued fractions], Applied Optics, vol 15, 668 (1976)). 
							 | 
						||
| 
								 | 
							
								Their convergence rates depend on ['x], therefore we need
							 | 
						||
| 
								 | 
							
								different strategies for large ['x] and small ['x].
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								['x > v], CF1 needs O(['x]) iterations to converge, CF2 converges rapidly.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								['x <= v], CF1 converges rapidly, CF2 fails to converge when ['x] [^->] 0.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When ['x] is large (['x] > 2), both continued fractions converge (CF1
							 | 
						||
| 
								 | 
							
								may be slow for really large ['x]). K[sub [mu]][space] and K[sub [mu]+1][space]
							 | 
						||
| 
								 | 
							
								can be calculated by
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel13]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								where
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel14]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								['S] is also a series that is summed along with CF2, see 
							 | 
						||
| 
								 | 
							
								I.J. Thompson and A.R. Barnett, ['Modified Bessel functions I_v and K_v
							 | 
						||
| 
								 | 
							
								    of real order and complex argument to selected accuracy], Computer Physics
							 | 
						||
| 
								 | 
							
								    Communications, vol 47, 245 (1987).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								When ['x] is small (['x] <= 2), CF2 convergence may fail (but CF1
							 | 
						||
| 
								 | 
							
								works very well). The solution here is Temme's series:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel15]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								where
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[equation mbessel16]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								f[sub k][space] and h[sub k][space]
							 | 
						||
| 
								 | 
							
								are also computed by recursions (involving gamma functions), but the
							 | 
						||
| 
								 | 
							
								formulas are a little complicated, readers are referred to 
							 | 
						||
| 
								 | 
							
								N.M. Temme, ['On the numerical evaluation of the modified Bessel function
							 | 
						||
| 
								 | 
							
								    of the third kind], Journal of Computational Physics, vol 19, 324 (1975).
							 | 
						||
| 
								 | 
							
								Note: Temme's series converge only for |[mu]| <= 1/2.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								K[sub [nu]](x) is then calculated from the forward 
							 | 
						||
| 
								 | 
							
								recurrence, as is K[sub [nu]+1](x). With these two values and
							 | 
						||
| 
								 | 
							
								f[sub [nu]], the Wronskian yields I[sub [nu]](x) directly.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[endsect]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								[/ 
							 | 
						||
| 
								 | 
							
								  Copyright 2006 John Maddock, Paul A. Bristow and Xiaogang Zhang.
							 | 
						||
| 
								 | 
							
								  Distributed under the Boost Software License, Version 1.0.
							 | 
						||
| 
								 | 
							
								  (See accompanying file LICENSE_1_0.txt or copy at
							 | 
						||
| 
								 | 
							
								  http://www.boost.org/LICENSE_1_0.txt).
							 | 
						||
| 
								 | 
							
								]
							 |